Search code examples
javafile-iozip

How do I change a ZipEntry name


I have the following code that writes a text file in a ZIP file:

FileOutputStream fOut = new FileOutputStream(fullFilename, false);
BufferedOutputStream bOut = new BufferedOutputStream(fOut);
ZipOutputStream zOut = new ZipOutputStream(bOut);

zOut.putNextEntry(new ZipEntry("aFile1.txt"));
//Do some processing and write to zOut...
zOut.write(...);
(...)
zOut.closeEntry();

zOut.close();
//Etc (close all resources)

I would need to change the filename of the zipEntry after it has been written (as its name will depend on its content written).

Also, it is not an option to write in a buffer and write to file only when final filename is known (because file size is potentially very large: not enough memory).


Solution

  • It is a missing functionality, which could have been simple, as the entries themselves are not compressed.

    The easiest way, requiring a rewrite though, is the zip FileSystem: since java 7 you may use a zip file as a virtual file system: writing, renaming and moving files in them. An example. You copy a file from the normal file system into the zip file system, and later rename the file in the zip.

    // Create the zip file:
    URI zipURI = URI.create("jar:file:" + fullFilename); // "jar:file:/.../... .zip"
    Map<String, Object> env = new HashMap<>(); 
    env.put("create", "true");
    FileSystem zipFS = FileSystems.newFileSystem(zipURI, env, null);
    
    // Write to aFile1.txt:
    Path pathInZipfile = zipFS.getPath("/aFile1.txt");
    BufferedWriter out = Files.newBufferedWriter(pathInZipfile,
            StandardCharsets.UTF_8, StandardOpenOption.CREATE_NEW);
    out.write("Press any key, except both shift keys\n");
    out.close();
    
    // Rename file:
    Path pathInZipfile2 = zipFS.getPath("/aFile2.txt");
    Files.move(pathInZipfile, pathInZipfile2);
    
    zipFS.close();
    

    In principle you could also keep your old code - without renaming. And use a zip file system just for renaming.