Java Zip Example to Zip single File and a Directory recursively

java.util.zip.ZipOutputStream can be used to compress a file into ZIP format. Since a zip file can contain multiple entries, ZipOutputStream uses java.util.zip.ZipEntry to represent a zip file entry.

ZIP File

Creating a zip archive for a single file is very easy, we need to create a ZipOutputStream object from the FileOutputStream object of destination file. Then we add a new ZipEntry to the ZipOutputStream and use FileInputStream to read the source file to ZipOutputStream object. Once we are done writing, we need to close ZipEntry and release all the resources.

Zip Directory in Java

Zipping a directory is little tricky, first we need to get the files list as absolute path and then process each one of them separately. We need to add a ZipEntry for each file and use FileInputStream to read the content of the source file to the ZipEntry corresponding to that file.

Here is the java program showing how to zip a single file or zip a directory in java.

package com.journaldev.files;

import java.io.File;
import java.io.FileInputStream;
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;

public class ZipFiles {
    
    List<String> filesListInDir = new ArrayList<String>();

    public static void main(String[] args) {
        File file = new File("/Users/pankaj/sitemap.xml");
        String zipFileName = "/Users/pankaj/sitemap.zip";
        
        File dir = new File("/Users/pankaj/tmp");
        String zipDirName = "/Users/pankaj/tmp.zip";
        
        zipSingleFile(file, zipFileName);
        
        ZipFiles zipFiles = new ZipFiles();
        zipFiles.zipDirectory(dir, zipDirName);
    }

    /**
     * This method zips the directory
     * @param dir
     * @param zipDirName
     */
    private void zipDirectory(File dir, String zipDirName) {
        try {
            populateFilesList(dir);
            //now zip files one by one
            //create ZipOutputStream to write to the zip file
            FileOutputStream fos = new FileOutputStream(zipDirName);
            ZipOutputStream zos = new ZipOutputStream(fos);
            for(String filePath : filesListInDir){
                System.out.println("Zipping "+filePath);
                //for ZipEntry we need to keep only relative file path, so we used substring on absolute path
                ZipEntry ze = new ZipEntry(filePath.substring(dir.getAbsolutePath().length()+1, filePath.length()));
                zos.putNextEntry(ze);
                //read the file and write to ZipOutputStream
                FileInputStream fis = new FileInputStream(filePath);
                byte[] buffer = new byte[1024];
                int len;
                while ((len = fis.read(buffer)) > 0) {
                    zos.write(buffer, 0, len);
                }
                zos.closeEntry();
                fis.close();
            }
            zos.close();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * This method populates all the files in a directory to a List
     * @param dir
     * @throws IOException
     */
    private void populateFilesList(File dir) throws IOException {
        File[] files = dir.listFiles();
        for(File file : files){
            if(file.isFile()) filesListInDir.add(file.getAbsolutePath());
            else populateFilesList(file);
        }
    }

    /**
     * This method compresses the single file to zip format
     * @param file
     * @param zipFileName
     */
    private static void zipSingleFile(File file, String zipFileName) {
        try {
            //create ZipOutputStream to write to the zip file
            FileOutputStream fos = new FileOutputStream(zipFileName);
            ZipOutputStream zos = new ZipOutputStream(fos);
            //add a new Zip Entry to the ZipOutputStream
            ZipEntry ze = new ZipEntry(file.getName());
            zos.putNextEntry(ze);
            //read the file and write to ZipOutputStream
            FileInputStream fis = new FileInputStream(file);
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) > 0) {
                zos.write(buffer, 0, len);
            }
            
            //Close the zip entry to write to zip file
            zos.closeEntry();
            //Close resources
            zos.close();
            fis.close();
            fos.close();
            System.out.println(file.getCanonicalPath()+" is zipped to "+zipFileName);
            
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

Output of the above program is:

/Users/pankaj/sitemap.xml is zipped to /Users/pankaj/sitemap.zip
Zipping /Users/pankaj/tmp/.DS_Store
Zipping /Users/pankaj/tmp/data/data.dat
Zipping /Users/pankaj/tmp/data/data.xml
Zipping /Users/pankaj/tmp/data/xmls/project.xml
Zipping /Users/pankaj/tmp/data/xmls/web.xml
Zipping /Users/pankaj/tmp/data.Xml
Zipping /Users/pankaj/tmp/DB.xml
Zipping /Users/pankaj/tmp/item.XML
Zipping /Users/pankaj/tmp/item.xsd
Zipping /Users/pankaj/tmp/ms/data.txt
Zipping /Users/pankaj/tmp/ms/project.doc

Notice that while logging files to zip in directory, I am printing absolute path but while adding zip entry, I am using relative path from the directory so that when we unzip it, it will create the same directory structure.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Current day month ye@r *