How to Create and Update Zip File in Java

In this tutorial, we’ll explore how to easily create ZIP files, including multiple files, multiple directories, and updating an existing ZIP file in Java.

Table of Contents:

1. Import Necessary Classes

We use the built-in Java utility classes for creating ZIP files:


import java.io.*;
import java.nio.file.*;
import java.util.zip.*;
import java.util.stream.Stream;

2. Creating a ZIP with Multiple Files and Directories

Here’s how we can compress multiple files and directories:

JavaZipExample.java

package com.mkyong.zip;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class JavaZipExample {

    public static void main(String[] args) {
        String[] files = {"file1.txt", "file2.txt"};
        String[] directories = {"folder1", "folder2"};
        String zipFile = "files.zip";

        try (FileOutputStream fos = new FileOutputStream(zipFile);
             ZipOutputStream zos = new ZipOutputStream(fos)) {

            // Adding files
            for (String file : files) {
                Path filePath = Paths.get(file);
                if (!Files.exists(filePath)) {
                    throw new FileNotFoundException("File does not exists: " + filePath);
                }
                addToZipFile(filePath, zos);
            }

            // Adding directories
            for (String dir : directories) {
                Path dirPath = Paths.get(dir);
                if (!Files.exists(dirPath) || !Files.isDirectory(dirPath)) {
                    throw new IOException("Directory does not exist: " + dirPath);
                }
                try (Stream<Path> paths = Files.walk(dirPath)) {
                    paths.filter(path -> !Files.isDirectory(path))
                            .forEach(path -> addToZipFile(path, zos));
                }
            }

            System.out.println("ZIP file created successfully!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void addToZipFile(Path file, ZipOutputStream zos) {
        try (FileInputStream fis = new FileInputStream(file.toFile())) {
            // Replace backslashes with forward slashes for compatibility
            String zipEntryName = file.toString().replace("\\", "/");
            zos.putNextEntry(new ZipEntry(zipEntryName));

            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) > 0) {
                zos.write(buffer, 0, len);
            }
            zos.closeEntry();
        } catch (IOException e) {
            System.err.println("Failed to zip file: " + file);
            e.printStackTrace();
        }
    }

}

The line file.toString().replace("\\", "/") ensures compatibility with ZIP file standards, which use forward slashes (/) as path separators. Java typically returns file paths with backslashes (\) on Windows. Replacing backslashes prevents issues when the ZIP file is extracted on other operating systems such as Linux or macOS.

3. Adding Files or Directories to an Existing ZIP File

To add new files or directories into an existing ZIP file, use this source code:

JavaAddToExistingZip.java

package com.mkyong.zip;

import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

public class JavaAddToExistingZip {

    private static void addToZipFile(Path file, ZipOutputStream zos) {
        try (FileInputStream fis = new FileInputStream(file.toFile())) {
            // Replace backslashes with forward slashes for compatibility
            String zipEntryName = file.toString().replace("\\", "/");
            zos.putNextEntry(new ZipEntry(zipEntryName));

            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) > 0) {
                zos.write(buffer, 0, len);
            }
            zos.closeEntry();
        } catch (IOException e) {
            System.err.println("Failed to zip file: " + file);
            e.printStackTrace();
        }
    }

    public static void addToExistingZip(String existingZipPath, String newPath) throws IOException {
        Path zipPath = Paths.get(existingZipPath);
        if (!Files.exists(zipPath)) {
            throw new IOException("ZIP file does not exist: " + existingZipPath);
        }

        Path tempZip = Files.createTempFile(null, null);

        try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(tempZip));
             ZipInputStream zis = new ZipInputStream(new FileInputStream(existingZipPath))) {

            ZipEntry entry;
            byte[] buffer = new byte[1024];

            // Copy existing ZIP entries to tempZip 
            while ((entry = zis.getNextEntry()) != null) {
                zos.putNextEntry(new ZipEntry(entry.getName()));
                int len;
                while ((len = zis.read(buffer)) > 0) {
                    zos.write(buffer, 0, len);
                }
                zos.closeEntry();
            }

            // Check if path is file or directory
            Path newPathObj = Paths.get(newPath);
            if (Files.isDirectory(newPathObj)) {
                try (Stream<Path> paths = Files.walk(newPathObj)) {
                    paths.filter(path -> !Files.isDirectory(path))
                            .forEach(path -> addToZipFile(path, zos));
                }
            } else {
                addToZipFile(newPathObj, zos);
            }
        }

        // Replace original ZIP with updated ZIP (tempZip)
        Files.move(tempZip, Paths.get(existingZipPath), StandardCopyOption.REPLACE_EXISTING);
    }

    public static void main(String[] args) throws IOException {

        String file = "newfile.txt";
        //String file = "newfolder";
        String zipFile = "existingfiles.zip";

        addToExistingZip(zipFile, file);

    }
}

4. References

34 comments on “How to Create and Update Zip File in Java

  1. Hi,
    just see your zip example here. it seems zip folder examples always zip the files and sub-folder, not include the starting folder itself. That seems different from standard tool like zip4j.
    For example, you zip folder: test, but test is not in the zip file, only files and sub-folder under test are zipped. I could be wrong though.
    Thanks,
    Oliver Yao

  2. Hi mkyong thank you for this example 5.Zip a folder or directory -FileSystems
    It’s working fine on linux but not on windows.

  3. Is there a way to create multiple txt files (without creating the txt files locally) which will be zipped and then send back to the user as a zipped folder? I have created a web service which enables the user to download a zipped folder with specific txt files. But in order to do that, I have to create the txt files locally -> zip them -> delete the txt files from the local storage.

    When the service is deployed, I am not allowed to create files on the server. I saw that some people mentioned to create the files in-memory but there are risks. There is a case that I might run out of memory.

    private File writeToFile(String lines, String fileName, File directoryName) throws IOException {
    
    		File file = new File(directoryName, fileName);
    
    		BufferedWriter writer = new BufferedWriter(new FileWriter(file));
    		writer.write(lines);
    
    		writer.close();
    		return file;
    	}
    

    The above method is used to create and return a File. I have a List<File> which contains all the txt files. I iterate the list and add the files into ZipOutputStream etc.

    What do you think I should do? Is there an example which I can see?

      1. The code on example 3 did not work for me when I used Postman to send a GET request (selected Send and Download).

        I used your code as like this:

        	@GetMapping("/test")
        	public void test() throws IOException {
        		reportService.testZipCreation();
        	}
        	public void testZipCreation() throws IOException {
        		zipFileWithoutSaveLocal("testZipCreation.zip");
        	}
        // create a file on demand (without save locally) and add to zip
        	private void zipFileWithoutSaveLocal(String zipFileName) throws IOException {
        
        	    String data = "Test data \n123\n456";
        	    String fileNameInZip = "abc.txt";
        
        	    try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFileName))) {
        	    	
        	        ZipEntry zipEntry = new ZipEntry(fileNameInZip);
        	        zos.putNextEntry(zipEntry);
        
        	        ByteArrayInputStream bais = new ByteArrayInputStream(data.getBytes());
        	        // one line, able to handle large size?
        	        //zos.write(bais.readAllBytes());
        
        	        // play safe
        	        byte[] buffer = new byte[1024];
        	        int len;
        	        while ((len = bais.read(buffer)) > 0) {
        	            zos.write(buffer, 0, len);
        	        }
        
        	        zos.closeEntry();
        	    }
        
        	}
        

        When I send a request from Postman, I was getting an empty txt file called response.txt.

        Maybe I did something incorrectly.

        1. I had to make a modification by providing an HttpServletResponse as an argument.

          Following, you can view the modifications:

          @GetMapping("/testV2")
          	public void testV2(HttpServletResponse response) throws IOException {
          		reportService.testZipCreationV2(response);
          	}
          
          public void testZipCreationV2(HttpServletResponse response) throws IOException {
          		
          		response.setContentType("application/octet-stream");
          		response.setHeader("Content-Disposition", "attachment;filename=testZipCreationV2.zip");
          		response.setHeader("Access-Control-Expose-Headers","Content-Disposition");
          		response.setStatus(HttpServletResponse.SC_OK);
          		
          		zipFileWithoutSaveLocalV2(response);
          	}
          
          // create a file on demand (without save locally) and add to zip
          	private void zipFileWithoutSaveLocalV2(HttpServletResponse response) throws IOException {
          
          	    String data = "Test data \n123\n456";
          	    String fileNameInZip = "abc.txt";
          
          	    try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) {
          
          	        ZipEntry zipEntry = new ZipEntry(fileNameInZip);
          	        zos.putNextEntry(zipEntry);
          
          	        ByteArrayInputStream bais = new ByteArrayInputStream(data.getBytes());
          	        // one line, able to handle large size?
          	        //zos.write(bais.readAllBytes());
          
          	        // play safe
          	        byte[] buffer = new byte[1024];
          	        int len;
          	        while ((len = bais.read(buffer)) > 0) {
          	            zos.write(buffer, 0, len);
          	        }
          
          	        zos.closeEntry();
          	    }
          	}
          

          I have to create a method that zips multiple txt files with different txt names.

      2. I managed to find a solution using the combination of example 3 and my code. The website does not allow me to delete my old comments in order to upload the code.

  4. Hello Mkyong,
    thanks for the example. Just one improvement:

    FileOutputStream fos = new FileOutputStream(zipFile);
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    ZipOutputStream zos = new ZipOutputStream(bos);

    Wrapping the FileOutputStream into a BufferedOutputStream will make zip-file creation MUCH faster.

    1. Try Files.copy at example 4, but I didn’t test if it will copy the file permission.

      If we unzip the file onto another file system or OS, should we apply the same the file permission?

  5. “great” example…Sry, but this example creates invalid ZIP files. Within ZIP files you should ALWAYS use forward slashes for paths – this is described within the ZIP standard (https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT). this example creates backward slashes for paths on windows file systems. I wouldn’t blame you, if you were using unix, but obviously you ARE using windows.
    Please adapt this to avoid others creating invalid ZIPs.

  6. I have a requirement to zip an XML file generated in the same code flow. I am marshalling a java object to outputstream. But I don’t want to write the XML file. Because all I need is the zip file, XML file is not being used later.

    I was trying to discover if we can directly zip the outputstream of xml into a zip file without creating the intermediate XML file.

    My last option would be, creating the XML file, then creating the ZIP file from it and then deleting the XML file.

    Please let me know if this is possible.

  7. Hi, thank you a lot, But It Has A Problem!!!
    if we get it an empty folder, it will throw exception, and also, if we have an empty folder in another folder, it doesn’t create that empty folder!

  8. Hello Sir,
    I have a requirement where client can download all uploaded file from server.
    I have done downloading for single file. But i am not able to allow user to download all file at a single click
    Please Help me with this. all files are image file and i am suppose to zip it and allow download to user pc.
    Thank you
    Praveen

  9. If i have a list of files, and i would like to rename it beofre zip it up, how could that be done?Can anyone advise? Many Thanks.

  10. The design for the blog is a tad off in Epiphany. Nevertheless I like your website. I may need to use a normal web browser just to enjoy it.

  11. Hi Yong,
    it’s necessary to considered that compressing directories which are empty in the example of ‘Advance ZIP example – Recursively’.
    thank you for sharing,I like the platform.

Leave a Comment

Your email address will not be published. Required fields are marked *