How do I compress or zip a directory recursively?

In this example you are going to learn how to zip or compress a directory recursively. The zip file format allows us to compress multiple files. We use the java.util.zip.ZipOutputStream to compress the file. Each entry in the zip file is represented by the java.util.zip.ZipEntry class.

To compress a directory we must first get all the list of files in the specified directory and including all files in the subdirectory. In the example this task is handled by the getFileList() method. This method store the file list in the fileList variable to be use later during the compression process to create the ZipEntry.

Below is the code example showing you how to compress multiple files using zip.

package org.kodejava.util.zip;

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 ZipDirectoryExample {
    private final List<String> fileList = new ArrayList<>();

    public static void main(String[] args) {
        String dir = "D:/Data";
        String zipFile = "D:/Data.zip";

        ZipDirectoryExample zip = new ZipDirectoryExample();
        zip.compressDirectory(dir, zipFile);
    }

    private void compressDirectory(String dir, String zipFile) {
        File directory = new File(dir);
        getFileList(directory);

        try (FileOutputStream fos = new FileOutputStream(zipFile);
             ZipOutputStream zos = new ZipOutputStream(fos)) {

            for (String filePath : fileList) {
                System.out.println("Compressing: " + filePath);

                // Creates a zip entry.
                String name = filePath.substring(directory.getAbsolutePath().length() + 1);

                ZipEntry zipEntry = new ZipEntry(name);
                zos.putNextEntry(zipEntry);

                // Read file content and write to zip output stream.
                try (FileInputStream fis = new FileInputStream(filePath)) {
                    byte[] buffer = new byte[1024];
                    int length;
                    while ((length = fis.read(buffer)) > 0) {
                        zos.write(buffer, 0, length);
                    }

                    // Close the zip entry.
                    zos.closeEntry();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Get files list from the directory recursive to the subdirectory.
     */
    private void getFileList(File directory) {
        File[] files = directory.listFiles();
        if (files != null && files.length > 0) {
            for (File file : files) {
                if (file.isFile()) {
                    fileList.add(file.getAbsolutePath());
                } else {
                    getFileList(file);
                }
            }
        }

    }
}

The code snippet above will compress the D:\Data directory, and it will produce a zip file called Data.zip. When running the program you can see something like this in the console:

Compressing: D:\Data\Aa.txt
Compressing: D:\Data\AA1a1.txt
Compressing: D:\Data\Bb.txt
Compressing: D:\Data\Cc.txt
Compressing: D:\Data\CC1c1.txt
Compressing: D:\Data\Dd.txt

How do I create checksum for a zip file?

This example demonstrate how to use CheckedOutputStream for creating a checksum of a zip file. Checksum can be used to detect whether a data was corrupted during a transmission process to a remote machine.

package org.kodejava.util.zip;

import java.io.*;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import java.util.zip.CheckedOutputStream;
import java.util.zip.Adler32;

public class ZipWithChecksum {
    public static void main(String[] args) throws Exception {
        String target = "data-1.zip";

        try (FileOutputStream fos = new FileOutputStream(target);
             // An output stream that also maintains a checksum of the data
             // being written. The checksum can then be used to verify the
             // integrity of the output data.
             CheckedOutputStream checksum =
                     new CheckedOutputStream(fos, new Adler32())) {
            try (ZipOutputStream zos =
                         new ZipOutputStream(new BufferedOutputStream(checksum))) {

                int size;
                byte[] buffer = new byte[1024];

                // Get all text files on the working folder.
                File dir = new File(".");
                String[] files = dir.list((directory, name) -> name.endsWith(".txt"));

                for (String file : Objects.requireNonNull(files)) {
                    System.out.println("Compressing: " + file);

                    try (FileInputStream fis = new FileInputStream(file);
                         BufferedInputStream bis =
                                 new BufferedInputStream(fis, buffer.length)) {

                        // put a new ZipEntry in the ZipOutputStream
                        ZipEntry zipEntry = new ZipEntry(file);
                        zos.putNextEntry(zipEntry);

                        // read data to the end of the source file and write it
                        // to the zip output stream.
                        while ((size = bis.read(buffer, 0, buffer.length)) > 0) {
                            zos.write(buffer, 0, size);
                        }

                        zos.closeEntry();
                    }
                }
            }

            // Print out checksum value
            long value = checksum.getChecksum().getValue();
            System.out.println("Checksum   : " + value);
        }
    }
}

How do I create a zip file?

package org.kodejava.util.zip;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZippingFileExample {
    public static void main(String[] args) {
        String source = "data.txt";
        String target = "data.zip";

        try (ZipOutputStream zos = 
                 new ZipOutputStream(new FileOutputStream(target));
             InputStream is = 
                 ZippingFileExample.class.getResourceAsStream("/" + source)) {
            if (is != null) {
                // Put a new ZipEntry in the ZipOutputStream
                zos.putNextEntry(new ZipEntry(source));

                int size;
                byte[] buffer = new byte[1024];

                // Read data to the end of the source file and write it
                // to the zip output stream.
                while ((size = is.read(buffer, 0, buffer.length)) > 0) {
                    zos.write(buffer, 0, size);
                }

                zos.closeEntry();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}