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 sub directory. 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.example.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 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,
                        filePath.length());
                ZipEntry zipEntry = new ZipEntry(name);
                zos.putNextEntry(zipEntry);

                //
                // Read file content and write to zip output stream.
                //
                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 and the file input stream.
                //
                zos.closeEntry();
                fis.close();
            }

            //
            // Close zip output stream and file output stream. This will
            // complete the compression process.
            //
            zos.close();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Get files list from the directory recursive to the sub directory.
     */
    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:\DataAa.txt
Compressing: D:\DataAA1a1.txt
Compressing: D:\DataBb.txt
Compressing: D:\DataCc.txt
Compressing: D:\DataCC1c1.txt
Compressing: D:\DataDd.txt

How do I decompress a GZip file in Java?

In the previous example we have learn how to compress a file in GZIP format. To get the file back to its original version we will now learn how to decompress the gzip file. Just like the previous example, we are also going to use the FileInputStream and FileOutputStream class to read the compressed source file and to write out the decompressed file. While GZipOutputStream was used to to create the gzip file, the GZipInputStream is the class that handles the decompression.

Here is your code snippet:

package org.kodejava.example.zip;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;

public class GZipDecompressExample {
    public static void main(String[] args) {
        //
        // GZip input and output file.
        //
        String sourceFile = "core-sample/target/classes/output.gz";
        String targetFile = "core-sample/target/classes/input-1.txt";

        try {
            //
            // Create a file input stream to read the source file.
            //
            FileInputStream fis = new FileInputStream(sourceFile);

            //
            // Create a gzip input stream to decompress the source
            // file defined by the file input stream.
            //
            GZIPInputStream gzis = new GZIPInputStream(fis);

            //
            // Create a buffer and temporary variable used during the
            // file decompress process.
            //
            byte[] buffer = new byte[1024];
            int length;

            //
            // Create file output stream where the decompress result
            // will be stored.
            //
            FileOutputStream fos = new FileOutputStream(targetFile);

            //
            // Read from the compressed source file and write the
            // decompress file.
            //
            while ((length = gzis.read(buffer)) > 0) {
                fos.write(buffer, 0, length);
            }

            //
            // Close the resources.
            //
            fos.close();
            gzis.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}