Java IO Tutorial

How to create Zip file in Java

This article shows a few examples to zip a single file and a whole directory (including sub-files and subdirectories).

  1. Zip a file – java.util.zip
  2. Zip a file – Files.copy to Zip FileSystems
  3. Zip a file on demand (without write to disk)
  4. Zip a folder – File tree and java.util.zip
  5. Zip a folder – File tree and Files.copy to Zip FileSystems
  6. zipj4 library

Java 7 introduced the Zip File System Provider, combines with Files.copy, we can copy the file attributes into the zip file easily (see example 4).

1. Zip a single file – java.util.zip

1.1 This Java example uses java.util.zip.ZipOutputStream to zip a single file.

ZipFileExample1.java

package com.mkyong.io.howto;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipFileExample1 {

    public static void main(String[] args) {

        Path source = Paths.get("/home/mkyong/test/Test.java");
        String zipFileName = "example.zip";

        try {

            ZipExample.zipSingleFile(source, zipFileName);

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("Done");

    }

    // Zip a single file
    public static void zipSingleFile(Path source, String zipFileName)
        throws IOException {

        if (!Files.isRegularFile(source)) {
            System.err.println("Please provide a file.");
            return;
        }

        try (
            ZipOutputStream zos = new ZipOutputStream(
                new FileOutputStream(zipFileName));
            FileInputStream fis = new FileInputStream(source.toFile());
        ) {

            ZipEntry zipEntry = new ZipEntry(source.getFileName().toString());
            zos.putNextEntry(zipEntry);

            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) > 0) {
                zos.write(buffer, 0, len);
            }
            zos.closeEntry();
        }

    }
}

Output

Terminal

$ unzip -l example.zip
Archive:  example.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
       32  2020-08-06 16:19   Test.java
---------                     -------
       32                     1 file

$ unzip example.zip
Archive:  example.zip
  inflating: Test.java               

2. Zip a single file – FileSystems

2.1 This example uses the Java 7 NIO FileSystems.newFileSystem to create a zip file and Files.copy to copy the files into the zip path.

ZipFileExample2.java

package com.mkyong.io.howto;

import java.io.*;
import java.net.URI;
import java.nio.file.*;
import java.util.HashMap;
import java.util.Map;

public class ZipFileExample2 {

    public static void main(String[] args) {

        Path source = Paths.get("/home/mkyong/test/Test.java");
        String zipFileName = "example.zip";

        try {

            ZipExample.zipSingleFileNio(source, zipFileName);

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("Done");

    }

    // Zip a single file
    public static void zipSingleFileNio(Path source, String zipFileName)
        throws IOException {

        if (!Files.isRegularFile(source)) {
            System.err.println("Please provide a file.");
            return;
        }

        Map<String, String> env = new HashMap<>();
        // Create the zip file if it doesn't exist
        env.put("create", "true");

        URI uri = URI.create("jar:file:/home/mkyong/" + zipFileName);

        try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
            Path pathInZipfile = zipfs.getPath(source.getFileName().toString());

            // Copy a file into the zip file path
            Files.copy(source, pathInZipfile, StandardCopyOption.REPLACE_EXISTING);
        }

    }


}

3. Zip a single file on demand

This example uses ByteArrayInputStream to directly create some bytes on demand and save it into the zip file without saving or writing the data into the local file system.


    // create a file on demand (without save locally) and add to zip
    public static 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();
        }

    }

Output

Terminal

$ unzip -l example.zip

Archive:  example.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
       18  2020-08-11 18:44   abc.txt
---------                     -------
       18                     1 file

4. Zip a folder or directory – java.util.zip

4.1 Review a directory that includes some sub-files and subdirectories.

Terminal

$ tree /home/mkyong/test
test
├── data
│   └── db.debug.conf
├── README.md
├── test-a1.log
├── test-a2.log
├── test-b
│   ├── test-b1.txt
│   ├── test-b2.txt
│   ├── test-c
│   │   ├── test-c1.log
│   │   └── test-c2.log
│   └── test-d
│       ├── test-d1.log
│       └── test-d2.log
└── Test.java

4.2 This Java example uses FileVisitor to walk a file tree and ZipOutputStream to zip everything manually, including sub-files and subdirectories, but ignore symbolic links and file attributes.

ZipDirectoryExample1.java

package com.mkyong.io.howto;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipDirectoryExample {

    public static void main(String[] args) {

        Path source = Paths.get("/home/mkyong/test/");

        if (!Files.isDirectory(source)) {
            System.out.println("Please provide a folder.");
            return;
        }

        try {

            ZipDirectoryExample.zipFolder(source);

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("Done");

    }

    // zip a directory, including sub files and sub directories
    public static void zipFolder(Path source) throws IOException {

        // get folder name as zip file name
        String zipFileName = source.getFileName().toString() + ".zip";

        try (
                ZipOutputStream zos = new ZipOutputStream(
                        new FileOutputStream(zipFileName))
        ) {

            Files.walkFileTree(source, new SimpleFileVisitor<>() {
                @Override
                public FileVisitResult visitFile(Path file,
                    BasicFileAttributes attributes) {

                    // only copy files, no symbolic links
                    if (attributes.isSymbolicLink()) {
                        return FileVisitResult.CONTINUE;
                    }

                    try (FileInputStream fis = new FileInputStream(file.toFile())) {

                        Path targetFile = source.relativize(file);
                        zos.putNextEntry(new ZipEntry(targetFile.toString()));

                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = fis.read(buffer)) > 0) {
                            zos.write(buffer, 0, len);
                        }

                        // if large file, throws out of memory
                        //byte[] bytes = Files.readAllBytes(file);
                        //zos.write(bytes, 0, bytes.length);

                        zos.closeEntry();

                        System.out.printf("Zip file : %s%n", file);

                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult visitFileFailed(Path file, IOException exc) {
                    System.err.printf("Unable to zip : %s%n%s%n", file, exc);
                    return FileVisitResult.CONTINUE;
                }
            });

        }

    }

}

Output

Terminal

Zip file : /home/mkyong/test/test-a2.log
Zip file : /home/mkyong/test/test-a1.log
Zip file : /home/mkyong/test/data/db.debug.conf
Zip file : /home/mkyong/test/README.md
Zip file : /home/mkyong/test/Test.java
Zip file : /home/mkyong/test/test-b/test-b1.txt
Zip file : /home/mkyong/test/test-b/test-c/test-c2.log
Zip file : /home/mkyong/test/test-b/test-c/test-c1.log
Zip file : /home/mkyong/test/test-b/test-b2.txt
Zip file : /home/mkyong/test/test-b/test-d/test-d2.log
Zip file : /home/mkyong/test/test-b/test-d/test-d1.log

Done

The above example creates the zip file at the current working directory, and we didn’t copy the file attributes (review the file created date and time).

Terminal

$ unzip -l test.zip

Archive:  test.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2020-08-06 18:49   test-a2.log
        0  2020-08-06 18:49   test-a1.log
       14  2020-08-06 18:49   data/db.debug.conf
       42  2020-08-06 18:49   README.md
       32  2020-08-06 18:49   Test.java
        0  2020-08-06 18:49   test-b/test-b1.txt
        0  2020-08-06 18:49   test-b/test-c/test-c2.log
        0  2020-08-06 18:49   test-b/test-c/test-c1.log
        0  2020-08-06 18:49   test-b/test-b2.txt
        0  2020-08-06 18:49   test-b/test-d/test-d2.log
        0  2020-08-06 18:49   test-b/test-d/test-d1.log
---------                     -------
       88                     11 files

5. Zip a folder or directory – FileSystems

5.1 This example uses the same FileVisitor to walk the file tree. Still, this time we use FileSystems URI to create the zip file, and Files.copy to copy the files into the zip path, including the file attributes, but ignore the symbolic link.

ZipDirectoryExample2.java

package com.mkyong.io.howto;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.Map;

public class ZipDirectoryExample {

    public static void main(String[] args) {

        Path source = Paths.get("/home/mkyong/test/");

        if (!Files.isDirectory(source)) {
            System.out.println("Please provide a folder.");
            return;
        }

        try {

            ZipDirectoryExample.zipFolderNio(source);

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("Done");

    }

    public static void zipFolderNio(Path source) throws IOException {

        // get current working directory
        String currentPath = System.getProperty("user.dir") + File.separator;

        // get folder name as zip file name
        // can be other extension, .foo .bar .whatever
        String zipFileName = source.getFileName().toString() + ".zip";
        URI uri = URI.create("jar:file:" + currentPath + zipFileName);

        Files.walkFileTree(source, new SimpleFileVisitor<>() {
            @Override
            public FileVisitResult visitFile(Path file,
                BasicFileAttributes attributes) {

                // Copying of symbolic links not supported
                if (attributes.isSymbolicLink()) {
                    return FileVisitResult.CONTINUE;
                }

                Map<String, String> env = new HashMap<>();
                env.put("create", "true");

                try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {

                    Path targetFile = source.relativize(file);
                    Path pathInZipfile = zipfs.getPath(targetFile.toString());

                    // NoSuchFileException, need create parent directories in zip path
                    if (pathInZipfile.getParent() != null) {
                        Files.createDirectories(pathInZipfile.getParent());
                    }

                    // copy file attributes
                    CopyOption[] options = {
                            StandardCopyOption.REPLACE_EXISTING,
                            StandardCopyOption.COPY_ATTRIBUTES,
                            LinkOption.NOFOLLOW_LINKS
                    };
                    // Copy a file into the zip file path
                    Files.copy(file, pathInZipfile, options);

                } catch (IOException e) {
                    e.printStackTrace();
                }

                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFileFailed(Path file, IOException exc) {
                System.err.printf("Unable to zip : %s%n%s%n", file, exc);
                return FileVisitResult.CONTINUE;
            }

        });

    }

}

Output

Terminal

$ unzip -l test.zip
Archive:  test.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2020-07-27 15:10   test-a2.log
        0  2020-07-23 14:55   test-a1.log
        0  2020-08-06 18:57   data/
       14  2020-08-04 14:07   data/db.debug.conf
       42  2020-08-05 19:04   README.md
       32  2020-08-05 19:04   Test.java
        0  2020-08-06 18:57   test-b/
        0  2020-07-24 15:49   test-b/test-b1.txt
        0  2020-08-06 18:57   test-b/test-c/
        0  2020-07-27 15:11   test-b/test-c/test-c2.log
        0  2020-07-27 15:11   test-b/test-c/test-c1.log
        0  2020-07-27 15:10   test-b/test-b2.txt
        0  2020-08-06 18:57   test-b/test-d/
        0  2020-07-27 15:11   test-b/test-d/test-d2.log
        0  2020-07-27 15:11   test-b/test-d/test-d1.log
---------                     -------
       88                     15 files

# unzip to an external folder abc
$ unzip test.zip -d abc

Archive:  test.zip
 inflating: abc/test-a2.log         
 inflating: abc/test-a1.log         
  creating: abc/data/
 inflating: abc/data/db.debug.conf  
 inflating: abc/README.md           
 inflating: abc/Test.java           
  creating: abc/test-b/
 inflating: abc/test-b/test-b1.txt  
  creating: abc/test-b/test-c/
 inflating: abc/test-b/test-c/test-c2.log  
 inflating: abc/test-b/test-c/test-c1.log  
 inflating: abc/test-b/test-b2.txt  
  creating: abc/test-b/test-d/
 inflating: abc/test-b/test-d/test-d2.log  
 inflating: abc/test-b/test-d/test-d1.log  

$ tree abc
abc
├── data
│   └── db.debug.conf
├── README.md
├── test-a1.log
├── test-a2.log
├── test-b
│   ├── test-b1.txt
│   ├── test-b2.txt
│   ├── test-c
│   │   ├── test-c1.log
│   │   └── test-c2.log
│   └── test-d
│       ├── test-d1.log
│       └── test-d2.log
└── Test.java

6. Zip file – zip4j

The zip4j is a popular zip library in Java; it has many advanced features like a password-protected zip file, split zip file, AES encryption, etc. Please visit the zip4j github for further documentation and usages.

Here’s are some common usages to zip files and folder.


import net.lingala.zip4j.ZipFile;

//...
  public static void zip4j() throws IOException {

      // zip file with a single file
      new ZipFile("filename.zip").addFile("file.txt");

      // zip file with multiple files
      List<File> files = Arrays.asList(
              new File("file1.txt"), new File("file2.txt"));
      new ZipFile("filename.zip").addFiles(files);

      // zip file with a folder
      new ZipFile("filename.zip").addFolder(new File("/home/mkyong/folder"));


  }

Download Source Code

$ git clone https://github.com/mkyong/core-java

$ cd java-io

References

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
34 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Petros
3 years ago

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?

Petros
3 years ago
Reply to  mkyong

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.

Petros
3 years ago
Reply to  mkyong

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.

Last edited 3 years ago by Petros
Petros
3 years ago
Reply to  Petros

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.

Petros
3 years ago
Reply to  mkyong

Thank you very much for your help!

Hannes S
6 years ago

“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.

Koushik Roy (bOyInDBoX)
8 years ago

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.

varun
6 years ago

Hi did you get the code? if you can you please share the code i am also facing the same problem please hep.

Andrew
11 years ago

Thank You

Oliver Yao
2 years ago

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

Mohini Chaudhari
3 years ago

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

Aaron
3 years ago

What about zip4jvm. Looks like it has more comressions and encryption methods. And pretty comfortable to use.
https://github.com/oleg-cherednik/zip4jvm

pp.
3 years ago

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.

Sahil
4 years ago

how to preserve file permissions with zip creation?

Sarthak
6 years ago

How can I create self Extract executable file using java ? any idea.

Joseph Selvaraj
8 years ago

Hi Kong, I tested this code , In last line “SOURCE_FOLDER.length()+1 ” , +1 is not required. Am I right?

Mohammad
10 years ago

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!

Hannes S
5 years ago
Reply to  Mohammad

Zip does not contain folders as such, but only files. Thus empty folders won’t be possible with zip.

Praveen
10 years ago

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

Mohammed Amine
10 years ago

Hi mkyong thank you for this section it is interesting but the code does not work it gives an empty archive 🙁

YoYo
10 years ago

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.

Pankaj
11 years ago

The closeEntry() call should be inside the for loop in compressing directory.

site
11 years ago

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.

GuoTao
11 years ago

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.

nagarjuna
12 years ago

can u send me the program for created zip file is automatically send to mail through our gmail……….

Give me reply to my mail [email protected]

Khaled
11 years ago
Reply to  nagarjuna

You can use Java mail to create an e-mail, attach that zip file and send it to that designated address.

abaynew
9 years ago
Reply to  Khaled

hllow dears

how to convert java code into jara files