This article shows a few examples to zip a single file and a whole directory (including sub-files and subdirectories).
- Zip a file –
java.util.zip
- Zip a file –
Files.copy
toZip FileSystems
- Zip a file on demand (without write to disk)
- Zip a folder – File tree and
java.util.zip
- Zip a folder – File tree and
Files.copy
toZip FileSystems
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.favtuts.io.howto.compress; import java.io.*; import java.nio.file.*; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipFileExample { public static void main(String[] args) { Path source = Paths.get("/home/tvt/workspace/favtuts/Test.java"); String zipFileName = "example.zip"; try { zipSingleFile(source, zipFileName); } catch (IOException e) { e.printStackTrace(); } } // 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
$ unzip -l example.zip
Archive: example.zip
Length Date Time Name
--------- ---------- ----- ----
1393 2022-05-20 11:35 Test.java
--------- -------
1393 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.favtuts.io.howto.compress; import java.io.*; import java.net.URI; import java.nio.file.*; import java.util.*; public class ZipFileExample { public static void main(String[] args) { Path source = Paths.get("/home/tvt/workspace/favtuts/Test.java"); String zipFileName = "example.zip"; try { 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/tvt/workspace/favtuts/"+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.
package com.favtuts.io.howto.compress; import java.io.*; import java.net.URI; import java.nio.file.*; import java.util.*; import java.util.zip.*; public class ZipFileExample { public static void main(String[] args) { String zipFileName = "example.zip"; try { zipFileWithoutSaveLocal(zipFileName); } catch (IOException e) { e.printStackTrace(); } System.out.println("Done"); } // 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
$ unzip -l example.zip
Archive: example.zip
Length Date Time Name
--------- ---------- ----- ----
18 2022-05-20 12:55 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.
$ tree /home/tvt/workspace/favtuts/test
test
├── data
│ └── db.debug.conf
├── file.txt
├── README.md
├── soft-link -> /home/tvt/workspace/favtuts/test/test-b/test-d/test-d2.log
├── 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
└── test.log
4 directories, 14 files
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.favtuts.io.howto.compress; import java.io.*; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.util.*; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipDirectoryExample { public static void main(String[] args) { Path source = Paths.get("/home/tvt/workspace/favtuts/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
Zip file : /home/tvt/workspace/favtuts/test/test-a1.log
Zip file : /home/tvt/workspace/favtuts/test/data/db.debug.conf
Zip file : /home/tvt/workspace/favtuts/test/test-a2.log
Zip file : /home/tvt/workspace/favtuts/test/file.txt
Zip file : /home/tvt/workspace/favtuts/test/Test.java
Zip file : /home/tvt/workspace/favtuts/test/test.log
Zip file : /home/tvt/workspace/favtuts/test/test-b/test-b2.txt
Zip file : /home/tvt/workspace/favtuts/test/test-b/test-d/test-d1.log
Zip file : /home/tvt/workspace/favtuts/test/test-b/test-d/test-d2.log
Zip file : /home/tvt/workspace/favtuts/test/test-b/test-c/test-c2.log
Zip file : /home/tvt/workspace/favtuts/test/test-b/test-c/test-c1.log
Zip file : /home/tvt/workspace/favtuts/test/test-b/test-b1.txt
Zip file : /home/tvt/workspace/favtuts/test/README.md
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).
$ unzip -l test.zip
Archive: test.zip
Length Date Time Name
--------- ---------- ----- ----
12 2022-05-20 13:20 test-a1.log
16 2022-05-20 13:20 data/db.debug.conf
12 2022-05-20 13:20 test-a2.log
9 2022-05-20 13:20 file.txt
1393 2022-05-20 13:20 Test.java
9 2022-05-20 13:20 test.log
12 2022-05-20 13:20 test-b/test-b2.txt
12 2022-05-20 13:20 test-b/test-d/test-d1.log
12 2022-05-20 13:20 test-b/test-d/test-d2.log
12 2022-05-20 13:20 test-b/test-c/test-c2.log
12 2022-05-20 13:20 test-b/test-c/test-c1.log
12 2022-05-20 13:20 test-b/test-b1.txt
11 2022-05-20 13:20 README.md
--------- -------
1534 13 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.favtuts.io.howto.compress; import java.io.*; import java.net.URI; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.util.*; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipDirectoryExample { public static void main(String[] args) { Path source = Paths.get("/home/tvt/workspace/favtuts/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
$ unzip -l test.zip
Archive: test.zip
Length Date Time Name
--------- ---------- ----- ----
12 2022-05-17 16:43 test-a1.log
0 2022-05-20 13:32 data/
16 2022-05-20 13:01 data/db.debug.conf
12 2022-05-17 16:43 test-a2.log
9 2022-05-18 10:27 file.txt
1393 2022-05-20 11:34 Test.java
9 2022-05-18 22:22 test.log
0 2022-05-20 13:32 test-b/
12 2022-05-17 16:44 test-b/test-b2.txt
0 2022-05-20 13:32 test-b/test-d/
12 2022-05-17 16:45 test-b/test-d/test-d1.log
12 2022-05-17 17:02 test-b/test-d/test-d2.log
0 2022-05-20 13:32 test-b/test-c/
12 2022-05-17 16:45 test-b/test-c/test-c2.log
12 2022-05-17 16:44 test-b/test-c/test-c1.log
12 2022-05-17 16:43 test-b/test-b1.txt
11 2022-05-20 13:02 README.md
--------- -------
1534 17 files
# unzip to an external folder abc
$ unzip test.zip -d abc
Archive: test.zip
inflating: abc/test-a1.log
creating: abc/data/
inflating: abc/data/db.debug.conf
inflating: abc/test-a2.log
inflating: abc/file.txt
inflating: abc/Test.java
inflating: abc/test.log
creating: abc/test-b/
inflating: abc/test-b/test-b2.txt
creating: abc/test-b/test-d/
inflating: abc/test-b/test-d/test-d1.log
inflating: abc/test-b/test-d/test-d2.log
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-b1.txt
inflating: abc/README.md
$ tree abc
abc
├── data
│ └── db.debug.conf
├── file.txt
├── 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
└── test.log
4 directories, 13 files
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/favtuts/folder")); }
Further Reading
Download Source Code
$ git clone https://github.com/favtuts/java-core-tutorials-examples
$ cd java-io/howto/compress