How can I add entries to an existing zip file in Java? [duplicate]

The function renames the existing zip file to a temporary file and then adds all entries in the existing zip along with the new files, excluding the zip entries that have the same name as one of the new files.

public static void addFilesToExistingZip(File zipFile,
         File[] files) throws IOException {
        // get a temp file
    File tempFile = File.createTempFile(zipFile.getName(), null);
        // delete it, otherwise you cannot rename your existing zip to it.
    tempFile.delete();

    boolean renameOk=zipFile.renameTo(tempFile);
    if (!renameOk)
    {
        throw new RuntimeException("could not rename the file "+zipFile.getAbsolutePath()+" to "+tempFile.getAbsolutePath());
    }
    byte[] buf = new byte[1024];

    ZipInputStream zin = new ZipInputStream(new FileInputStream(tempFile));
    ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile));

    ZipEntry entry = zin.getNextEntry();
    while (entry != null) {
        String name = entry.getName();
        boolean notInFiles = true;
        for (File f : files) {
            if (f.getName().equals(name)) {
                notInFiles = false;
                break;
            }
        }
        if (notInFiles) {
            // Add ZIP entry to output stream.
            out.putNextEntry(new ZipEntry(name));
            // Transfer bytes from the ZIP file to the output file
            int len;
            while ((len = zin.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
        }
        entry = zin.getNextEntry();
    }
    // Close the streams        
    zin.close();
    // Compress the files
    for (int i = 0; i < files.length; i++) {
        InputStream in = new FileInputStream(files[i]);
        // Add ZIP entry to output stream.
        out.putNextEntry(new ZipEntry(files[i].getName()));
        // Transfer bytes from the file to the ZIP file
        int len;
        while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        // Complete the entry
        out.closeEntry();
        in.close();
    }
    // Complete the ZIP file
    out.close();
    tempFile.delete();
}

You could use zipFile.entries() to get an enumeration of all of the ZipEntry objects in the existing file, loop through them and add them all to the ZipOutputStream, and then add your new entries in addition.


Here is a detailed article from JavaWorld on modifying zip archives.


You have to be sure to add a CRC32 for uncompressed files added to a zip. Check out the example here. http://jcsnippets.atspace.com/java/input-output/create-zip-file.html


You can do it in a simple way, without rewriting everything, with Zip4j. Here it shows: http://blog.michalszalkowski.com/java/zip4j-add-file-to-existing-zip-file/

And you can do it using Zip4J's ZipOutputStream too, using SplitOutputStream together.

<dependency>
    <groupId>net.lingala.zip4j</groupId>
    <artifactId>zip4j</artifactId>
    <version>1.3.1</version>
</dependency>

ex:

ZipFile zipFile = new ZipFile(new File("/home/szalek/zip/core1.zip"));

ArrayList filesToAdd = new ArrayList();
filesToAdd.add(new File("/home/szalek/zip/someData.txt"));

ZipParameters parameters = new ZipParameters();
parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);

//password
parameters.setEncryptFiles(true);
parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD);
parameters.setPassword("test123!");
//password

zipFile.addFiles(filesToAdd, parameters);