javaapache-commonsapache-commons-compress

Java selectively copy files from a zip such that file timestamp should be preserved


I have followed following approach to decompress a zip using apache commons compress:

But since I am using OutputStream & IOUtils.copy(ais, os); (code below) to unzip and copy file, the timestamp is not preserved. Is there another way to directly copy the file from the zip such that file timestamp can be preserved.

try (ArchiveInputStream ais =
         asFactory.createArchiveInputStream(
           new BufferedInputStream(
             new FileInputStream(archive)))) {

        System.out.println("Extracting!");
        ArchiveEntry ae;
        while ((ae = ais.getNextEntry()) != null) {
            // check if file needs to be extracted {}
            if(!extract())
                continue;

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

EDIT: With the help of jbx's answer below, following change will make it work.

IOUtils.copy(ais, os);
os.close();
outFile.setLastModified(entry.getLastModifiedTime().toMillis()); // this line

Solution

  • You could set the lastModifiedTime file attribute using NIO. Do it to the file exactly after you write it (after you close it). The operating system would have marked its last modified time to the current time at that point.

    https://docs.oracle.com/javase/tutorial/essential/io/fileAttr.html

    You will need to get the last modified time from the zip file, so maybe using NIO's Zip Filesystem Provider` to browse and extract files from the archive would be better than your current approach (unless the APIs you are using provide you the same information).

    https://docs.oracle.com/javase/7/docs/technotes/guides/io/fsp/zipfilesystemprovider.html