How to create Zip file in Java

author image

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

References

  • Zip File System Provider
  • ZIP File Format Specification
  • FileVisitor JavaDoc
  • How to get the current working directory in Java
  • ZipOutputStream JavaDoc
  • zip4j github
  • How to unzip a zip file in Java

author image

Comments