Как удалить ZIP-архив после распаковки с помощью Commons Compress в Java?
Я написал программу, которая распаковывает ZIP-архив, а затем рекурсивно распаковывает или извлекает найденные в нем архивы. Архивы внутри ZIP могут быть tar-файлами или ZIP-архивами, и я могу извлечь их просто отлично.
После извлечения внутренних архивов в каком-то новом каталоге я хочу их удалить. Это прекрасно работает для архивов tar, но по некоторым причинам не будет работать для архивов ZIP. Я закрыл все потоки, и в случае неудачного удаления я использую deleteOnExit в качестве отказоустойчивого, но это тоже не работает.
try (ArchiveInputStream ais =
asFactory.createArchiveInputStream(
new BufferedInputStream(
new FileInputStream(archive)))) {
System.out.println("Extracting!");
ArchiveEntry ae;
while ((ae = ais.getNextEntry()) != null) {
if (ae.isDirectory()) {
File dir = new File(archive.getParentFile(), ae.getName());
dir.mkdirs();
continue;
}
File f = new File(archive.getParentFile(), ae.getName());
File parent = f.getParentFile();
parent.mkdirs();
try (OutputStream os = new FileOutputStream(f)) {
IOUtils.copy(ais, os);
os.close();
} catch (IOException innerIoe) {
...
}
}
ais.close();
if (!archive.delete()) {
System.out.printf("Could not remove archive %s%n",
archive.getName());
archive.deleteOnExit();
}
} catch (IOException ioe) {
...
}
Не должно быть открытых потоков, если только закрытие ArchiveInputStream фактически не закроет поток. Но опять же, это работает для архивов tar.
Я где-то читал, что можно удалить ZIP-архивы, вызвав listFiles() для родительского файла, найти ZIP-архив и удалить его, но это звучит как странный запутанный процесс. Должен быть какой-то более простой способ.
РЕДАКТИРОВАТЬ:
Проблема специфична для Windows. В Linux (SliTaz 4 и Red Hat Enterprise 5) это прекрасно работает. Это говорит мне о том, что Windows как-то блокирует ZIP-архивы, что кажется немного странным.
1 ответ
К сожалению, довольно часто файлы, принадлежащие закрытым потокам, нельзя удалить в Windows. Иногда вам нужно немного подождать, а иногда даже этого недостаточно, и вам необходим цикл сбора мусора.
Например, это привело к муравьям FileUtils#tryHardToDelete
https://github.com/apache/ant/blob/master/src/main/org/apache/tools/ant/util/FileUtils.java#L1569 - и даже это, как известно, иногда приводит к зависанию файлов, и в этом случае File#deleteOnExec
это ваша лучшая ставка.