Я работаю над свинг-приложением, которое опирается на встроенную базу данных H2. Поскольку я не хочу связывать базу данных с приложением (база данных часто обновляется, и я хочу, чтобы новые пользователи приложения начинали с последней копии), я реализовал решение, которое загружает сжатую копию базы данных. Первый раз приложение запускается и извлекает его. Поскольку процесс извлечения может быть медленным, я добавил ProgressMonitorInputStream , чтобы показать прогресс процесса извлечения - к сожалению, когда начинается извлечение, появляется диалоговое окно хода выполнения, но оно вообще не обновляется. Кажется, что события достигают потока отправки событий. Вот метод:
public static String extractDbFromArchive(String pathToArchive) {
if (SwingUtilities.isEventDispatchThread()) {
System.out.println("Invoking on event dispatch thread");
}
// Get the current path, where the database will be extracted
String currentPath = System.getProperty("user.home") + File.separator + ".spellbook" + File.separator;
LOGGER.info("Current path: " + currentPath);
try {
//Open the archive
FileInputStream archiveFileStream = new FileInputStream(pathToArchive);
// Read two bytes from the stream before it used by CBZip2InputStream
for (int i = 0; i < 2; i++) {
archiveFileStream.read();
}
// Open the gzip file and open the output file
CBZip2InputStream bz2 = new CBZip2InputStream(new ProgressMonitorInputStream(
null,
"Decompressing " + pathToArchive,
archiveFileStream));
FileOutputStream out = new FileOutputStream(ARCHIVED_DB_NAME);
LOGGER.info("Decompressing the tar file...");
// Transfer bytes from the compressed file to the output file
byte[] buffer = new byte[1024];
int len;
while ((len = bz2.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
// Close the file and stream
bz2.close();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
try {
TarInputStream tarInputStream = null;
TarEntry tarEntry;
tarInputStream = new TarInputStream(new ProgressMonitorInputStream(
null,
"Extracting " + ARCHIVED_DB_NAME,
new FileInputStream(ARCHIVED_DB_NAME)));
tarEntry = tarInputStream.getNextEntry();
byte[] buf1 = new byte[1024];
LOGGER.info("Extracting tar file");
while (tarEntry != null) {
//For each entry to be extracted
String entryName = currentPath + tarEntry.getName();
entryName = entryName.replace('/', File.separatorChar);
entryName = entryName.replace('\\', File.separatorChar);
LOGGER.info("Extracting entry: " + entryName);
FileOutputStream fileOutputStream;
File newFile = new File(entryName);
if (tarEntry.isDirectory()) {
if (!newFile.mkdirs()) {
break;
}
tarEntry = tarInputStream.getNextEntry();
continue;
}
fileOutputStream = new FileOutputStream(entryName);
int n;
while ((n = tarInputStream.read(buf1, 0, 1024)) > -1) {
fileOutputStream.write(buf1, 0, n);
}
fileOutputStream.close();
tarEntry = tarInputStream.getNextEntry();
}
tarInputStream.close();
} catch (Exception e) {
}
currentPath += "db" + File.separator + DB_FILE_NAME;
if (!currentPath.isEmpty()) {
LOGGER.info("DB placed in : " + currentPath);
}
return currentPath;
}
Этот метод вызывается в потоке диспетчеризации событий (SwingUtilities.isEventDispatchThread () возвращает true), поэтому компоненты пользовательского интерфейса должны быть обновлены. Я не реализовал это как SwingWorker, так как мне все равно нужно ждать извлечения, прежде чем я смогу приступить к инициализации программы. Этот метод вызывается до того, как основной JFrame приложения станет видимым. Я не хочу, чтобы решение на основе свойства SwingWorker + изменило слушателей - я думаю, что ProgressMonitorInputStream - это именно то, что мне нужно, но я полагаю, что я что-то не так делаю правильно. Я использую Sun JDK 1.6.18. Любая помощь будет принята с благодарностью.