How to zip directories programmatically using Java
- Details
- Written by Nam Ha Minh
- Last Updated on 27 July 2019   |   Print Email
This article is about how to write a utility class for adding files and directories into a compressed zip archive, using built-in Java API.
The java.util.zip package provides the following classes for adding files and directories into a ZIP archive:
ZipOutputStream: this is the main class which can be used for making zip file and adding files and directories (entries) to be compressed in a single archive. Here are some important usages of this class:
- create a zip via its constructor ZipOutputStream(FileOutputStream)
- add entries of files and directories via method putNextEntry(ZipEntry)
- write binary data to current entry via method write(byte[] bytes, int offset, int length)
- close current entry via method closeEntry()
- save and close the zip file via method close()
ZipEntry: this class represents an entry to be added to the zip file. Its constructor takes a String which represents path of the file/directory being added. The path must be in the following form:
folder_1/subfolder_1/subfolder_2/…/subfolder_n/file.ext
In addition, the BufferedInputStream class is used to read content of input file via its method read(byte[]). While reading file’s content, write the bytes read into the current zip entry via ZipOutputStream’s write() method.
Following is source code of ZipUtility.java class:
import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * This utility compresses a list of files to standard ZIP format file. * It is able to compress all sub files and sub directories, recursively. * @author www.codejava.net * */ public class ZipUtility { /** * A constants for buffer size used to read/write data */ private static final int BUFFER_SIZE = 4096; /** * Compresses a list of files to a destination zip file * @param listFiles A collection of files and directories * @param destZipFile The path of the destination zip file * @throws FileNotFoundException * @throws IOException */ public void zip(List<File> listFiles, String destZipFile) throws FileNotFoundException, IOException { ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(destZipFile)); for (File file : listFiles) { if (file.isDirectory()) { zipDirectory(file, file.getName(), zos); } else { zipFile(file, zos); } } zos.flush(); zos.close(); } /** * Compresses files represented in an array of paths * @param files a String array containing file paths * @param destZipFile The path of the destination zip file * @throws FileNotFoundException * @throws IOException */ public void zip(String[] files, String destZipFile) throws FileNotFoundException, IOException { List<File> listFiles = new ArrayList<File>(); for (int i = 0; i < files.length; i++) { listFiles.add(new File(files[i])); } zip(listFiles, destZipFile); } /** * Adds a directory to the current zip output stream * @param folder the directory to be added * @param parentFolder the path of parent directory * @param zos the current zip output stream * @throws FileNotFoundException * @throws IOException */ private void zipDirectory(File folder, String parentFolder, ZipOutputStream zos) throws FileNotFoundException, IOException { for (File file : folder.listFiles()) { if (file.isDirectory()) { zipDirectory(file, parentFolder + "/" + file.getName(), zos); continue; } zos.putNextEntry(new ZipEntry(parentFolder + "/" + file.getName())); BufferedInputStream bis = new BufferedInputStream( new FileInputStream(file)); long bytesRead = 0; byte[] bytesIn = new byte[BUFFER_SIZE]; int read = 0; while ((read = bis.read(bytesIn)) != -1) { zos.write(bytesIn, 0, read); bytesRead += read; } zos.closeEntry(); } } /** * Adds a file to the current zip output stream * @param file the file to be added * @param zos the current zip output stream * @throws FileNotFoundException * @throws IOException */ private void zipFile(File file, ZipOutputStream zos) throws FileNotFoundException, IOException { zos.putNextEntry(new ZipEntry(file.getName())); BufferedInputStream bis = new BufferedInputStream(new FileInputStream( file)); long bytesRead = 0; byte[] bytesIn = new byte[BUFFER_SIZE]; int read = 0; while ((read = bis.read(bytesIn)) != -1) { zos.write(bytesIn, 0, read); bytesRead += read; } zos.closeEntry(); } }
The ZipUtility class has two public methods for adding files and directories to a zip archive:
- zip(List<File> listFiles, String destZipFile): accepts a list of File objects to be added to the destZipFile.
- zip(String[] files, String destZipFile): accepts an array of file paths to be added to the destZipFile.
And source code of a test class, ZipUtilityTest.java:
/** * A console application that tests the ZipUtility class * @author www.codejava.net * */ public class ZipUtilityTest { public static void main(String[] args) { String[] myFiles = {"E:/Test/PIC1.JPG", "E:/Test/PIC2.JPG", "E:/Test/PIC3.JPG", "E:/Test/PIC4.JPG"}; String zipFile = "E:/Test/MyPics.zip"; ZipUtility zipUtil = new ZipUtility(); try { zipUtil.zip(myFiles, zipFile); } catch (Exception ex) { // some errors occurred ex.printStackTrace(); } } }
Related Java Zip File Tutorials:
- How to compress files in ZIP format in Java
- How to read contents of a ZIP file in Java
- How to extract a zip file in Java
Other Java File IO Tutorials:
- How to Read and Write Text File in Java
- How to Read and Write Binary Files in Java
- Java IO - Common File and Directory Operations Examples
- Java Serialization Basic Example
- Understanding Java Externalization with Examples
- How to execute Operating System Commands in Java
- 3 ways for reading user's input from console in Java
- File change notification example with Watch Service API
- Java Scanner Tutorial and Code Examples
Comments
Your code was really useful for me.
Just one question, I have some norwegian character in my file name. Any advise on how to set an encoding with FileInputStream ? Thanks