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).
- 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.
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
$ 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.
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
$ 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.
$ 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.
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
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).
$ 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.
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
$ 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"));
}
Further Reading
How to unzip a zip file in Java
Download Source Code
$ git clone https://github.com/mkyong/core-java
$ cd java-io
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.
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?
Thanks for your feedback. We updated the code again, see example 3 – zip a file on demand.
The idea is using `ByteArrayInputStream` to create some data or bytes, and write it to `ZipOutputStream` directly.
Alternatively, create the files in the system temp folder.
https://mkyong.com/java/how-to-create-temporary-file-in-java/
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.
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:
When I send a request from Postman, I was getting an empty txt file called response.txt.
Maybe I did something incorrectly.
I had to make a modification by providing an HttpServletResponse as an argument.
Following, you can view the modifications:
I have to create a method that zips multiple txt files with different txt names.
Thank you very much for your help!
“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.
We updated the article with more examples, the
FileVisitor
andPaths
should solve the issue.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.
Hi did you get the code? if you can you please share the code i am also facing the same problem please hep.
Thank You
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
Hi mkyong thank you for this example 5.Zip a folder or directory -FileSystems
It’s working fine on linux but not on windows.
What about zip4jvm. Looks like it has more comressions and encryption methods. And pretty comfortable to use.
https://github.com/oleg-cherednik/zip4jvm
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.
Thanks for your feedback, I didn’t know about it.
how to preserve file permissions with zip creation?
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?
How can I create self Extract executable file using java ? any idea.
self extract executable file… sorry, I don’t know
Hi Kong, I tested this code , In last line “SOURCE_FOLDER.length()+1 ” , +1 is not required. Am I right?
We updated the example with
FileVisitor
; this question is no longer relevant.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!
Zip does not contain folders as such, but only files. Thus empty folders won’t be possible with zip.
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
Hi mkyong thank you for this section it is interesting but the code does not work it gives an empty archive 🙁
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.
The closeEntry() call should be inside the for loop in compressing directory.
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.
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.
We updated the article, try
FileVisitor
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]
You can use Java mail to create an e-mail, attach that zip file and send it to that designated address.
hllow dears
how to convert java code into jara files