javaapache-commons-compress

How to delete ZIP archive after decompressing with Commons Compress in Java?


I've written a program that decompresses a ZIP archive, then recursively decompresses or extracts archives found in it. The archives within the ZIP may be tar or ZIP archives and I can extract them just fine.

After extracting the inner archives within some new directory, I want to delete them. This works just fine for tar archives, but for some reason it will not work for ZIP archives. I've closed all streams, and should deletion fail I use deleteOnExit as a fail-safe, but that doesn't work either.

    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) {
        ...
    }

There should be no open streams, unless closing the ArchiveInputStream doesn't actually close the stream. But again this works for tar archives.

I read somewhere that one can manage to delete ZIP archives calling listFiles() on the parent file and locating the ZIP archive and deleting it, but this sounds like a weird convoluted process. There must be some simpler way.

EDIT:

The problem is specific to Windows. On Linux (SliTaz 4 and Red Hat Enterprise 5) this works perfectly fine. This tells me that Windows is somehow locking the ZIP archives, which seems a bit strange.


Solution

  • Unfortunately it is quite common that files belonging to streams you have closed just now cannot be deleted on Windows. Sometimes you need to wait a little and sometimes even that is not enough and you need a garbage collection cycle.

    For example this has lead to Ant's FileUtils#tryHardToDelete https://github.com/apache/ant/blob/master/src/main/org/apache/tools/ant/util/FileUtils.java#L1569 - and even that is known to sometimes leave files dangling, in which case File#deleteOnExec is your best bet.