Как удалить 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 это ваша лучшая ставка.

Другие вопросы по тегам