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 compress a file in Gzip format?

In this code example we will learn how to compress a file using the gzip compression. By its nature, gzip can only compress a single file, you can not use it for compressing a directory and all the files in that directory.

Classes that you will be using to compress a file in gzip format includes the GZipOutputStream, FileInputStream and FileOutputStream classes. The steps for compressing a file described in the comments of the code snippet below.

package org.kodejava.util.zip;

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

public class GZipCompressExample {
    public static void main(String[] args) {
        // GZip input and output file.
        String sourceFile = "data.txt";
        String targetFile = "output.gz";

        try (
                // Create a file input stream of the file that is going to be
                // compressed.
                FileInputStream fis = new FileInputStream(sourceFile);

                // Create a file output stream then write the gzip result into
                // a specified file name.
                FileOutputStream fos = new FileOutputStream(targetFile);

                // Create a gzip output stream object with file output stream
                // as the argument.
                GZIPOutputStream gzos = new GZIPOutputStream(fos)) {

            // Define buffer and temporary variable for iterating the file
            // input stream.
            byte[] buffer = new byte[1024];
            int length;

            // Read all the content of the file input stream and write it
            // to the gzip output stream object.
            while ((length = fis.read(buffer)) > 0) {
                gzos.write(buffer, 0, length);
            }

            // Finish file compressing and close all streams.
            gzos.finish();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

How do I compress Java objects?

This example demonstrates how to compress a Java object. We compress the Java object using GZIPOutputStream, pass it to ObjectOutputStream to write the object into an external file. The object we are going to compress will be represented by the User object. We need to make the User object serializable, so it must implement the java.io.Serializable interface. You can see the complete code snippet below.

package org.kodejava.util.zip;

import org.kodejava.util.support.User;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.zip.GZIPOutputStream;

public class ZipObjectDemo {
    public static void main(String[] args) {
        User admin = new User();
        admin.setId(1L);
        admin.setUsername("admin");
        admin.setPassword("secret");
        admin.setFirstName("System");
        admin.setLastName("Administrator");

        User foo = new User();
        foo.setId(2L);
        foo.setUsername("foo");
        foo.setPassword("secret");
        foo.setFirstName("Foo");
        foo.setLastName("Bar");

        System.out.println("Zipping....");
        System.out.println(admin);
        System.out.println(foo);

        File file = new File("user.dat");
        try (FileOutputStream fos = new FileOutputStream(file);
             GZIPOutputStream gos = new GZIPOutputStream(fos);
             ObjectOutputStream oos = new ObjectOutputStream(gos)) {

            oos.writeObject(admin);
            oos.writeObject(foo);
            oos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
package org.kodejava.util.support;

import java.io.Serializable;

public class User implements Serializable {
    private Long id;
    private String username;
    private String password;
    private String firstName;
    private String lastName;

    public User() {
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                '}';
    }
}

Running the code snippet will give us the following output:

Zipping....
User{id=1, username='admin', password='secret', firstName='System', lastName='Administrator'}
User{id=2, username='foo', password='secret', firstName='Foo', lastName='Bar'}

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();
        }
    }
}