Java – Zip Folder Tutorial

Learn how to zip a folder in Java

“Quotation, n: The act of repeating erroneously the words of another.”
― Ambrose Bierce, The Unabridged Devil’s Dictionary

1. Introduction

Java provides good support for reading and writing zip files. In this article, let us learn how to create a zip file from the contents of a folder in java.

2. Listing Folder Entries

The first step is to collect all entries in a folder, including the entries in the sub-directories. We use the easy file walker API for this purpose.

Here is an example of listing everything in a folder.

import java.nio.file.Paths;
import java.nio.file.Files;
import java.nio.file.Path;

Files
    .walk(Paths.get(name))
    .forEach(System.out::println);

We use the Stream.forEach() below with a lambda to add entries to the zip file.

3. Creating the Zip Output Stream

To write a zip file, we need a ZipOutputStream which provides the needed methods to add entries to a zip file and more.

String zipFile = ...;
FileOutputStream fout = new FileOutputStream(zipFile);
ZipOutputStream zout = new ZipOutputStream(fout);

4. Adding an Entry to a Zip File

Once the zip output stream is open for writing, we add a zip entry using the following code block.

ZipEntry ze = ...;
zout.putNextEntry(ze);
// write data here
zout.closeEntry();

The putNextEntry() positions the zip output stream correctly so data can be written to the stream. For each entry, the input file is opened and its contents written to the zip output stream.

try (FileInputStream in = new FileInputStream(path.toFile());) {
    byte[] buf = new byte[4096];
    int len;
    while ((len = in.read(buf)) != -1)
        zout.write(buf, 0, len);
}

5. Setting the File Attributes Correctly

For each zip file entry, the original file creation time, last modified time and last access time can be set. The attributes of the file are read using Files.readAttributes() with the BasicFileAttributes class.

BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class);
ZipEntry ze = ...;
ze
    .setCreationTime(attr.creationTime())
    .setLastAccessTime(attr.lastAccessTime())
    .setLastModifiedTime(attr.lastModifiedTime());

6. Adding Directory Entries

Directory entries are added to the zip file by making sure the entry name ends with a /.

File file = path.toFile();
ZipEntry ze = null;
if ( file.isDirectory() ) ze = new ZipEntry(file.toString() + "/");
else ze = new ZipEntry(file.toString());

7. The Complete Code

And here is the complete code, with all error checking and exception handling included.

static private void addEntry(Path path,ZipOutputStream zout) {
    BasicFileAttributes attr = null;
    try {
        attr = Files.readAttributes(path, BasicFileAttributes.class);
    } catch(java.io.IOException ex) {
        throw new RuntimeException(ex);
    }

    File file = path.toFile();
    ZipEntry ze = null;
    if ( file.isDirectory() ) ze = new ZipEntry(file.toString() + "/");
    else ze = new ZipEntry(file.toString());
    ze
        .setCreationTime(attr.creationTime())
        .setLastAccessTime(attr.lastAccessTime())
        .setLastModifiedTime(attr.lastModifiedTime());
    try {
        zout.putNextEntry(ze);
        if ( ! file.isDirectory() ) {
            try (FileInputStream in = new FileInputStream(path.toFile());) {
                byte[] buf = new byte[4096];
                int len;
                while ((len = in.read(buf)) != -1)
                    zout.write(buf, 0, len);
            }
        }
    } catch(java.io.IOException ex) {
        throw new RuntimeException(ex);
    } finally {
        try { zout.closeEntry(); }
        catch(java.io.IOException ex) { throw new RuntimeException(ex); }
    }
}

static public void main(String[] args) throws Exception {
    String zipFile = ...;
    String folder = ...;
    try(FileOutputStream fout = new FileOutputStream(zipFile);
        ZipOutputStream zout = new ZipOutputStream(fout);) {
        Files
            .walk(Paths.get(folder))
            .forEach(x -> addEntry(x, zout));
    }
}

Conclusion

This tutorial explained the basics of zipping a folder with all its entries using java. We use the file walker API to collect the entries and sub-entries in a folder, and stuff the data into a zip file. Directories are added to the zip file by appending a / to the entry name.