How to Create a Zip File in Java

Naveen AnamaneniUpdated · 4 min read
mediumJava 25javafileszip

A zip file is an archive that packs many files into one, usually compressed so it takes less space. Java can create zip files with the ZipOutputStream class in java.util.zip. You add each file as a ZipEntry (a name inside the archive), write its bytes, and close the entry. In this lesson, you will learn how to create a zip file from text, from files and from a whole folder, and then build a small tool that zips the largest files in a folder tree.

Steps to Create a Zip File

  1. Open a ZipOutputStream over a file output stream.
  2. For each file, call putNextEntry(new ZipEntry("name/inside/zip.txt")).
  3. Write the file's bytes to the zip stream.
  4. Call closeEntry().
  5. Close the zip stream (try-with-resources does it).

Classes and Methods

Class / methodDescription
ZipOutputStream(OutputStream out)It is used to write a zip archive to a stream.
ZipEntry(String name)It names one entry; use / for folders inside the zip.
putNextEntry(entry)It starts a new entry.
closeEntry()It finishes the current entry.
setLevel(int level)It sets compression from 0 (none) to 9 (best).

Example: Zipping Two Text Files

Let's see an example that creates two files and zips them.

MakeZip.java▶ Try it
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
 
public class MakeZip {
    public static void main(String[] args) throws IOException {
        Path a = Files.writeString(Path.of("navika.txt"),
                                   "Navika ".repeat(200));
        Path b = Files.writeString(Path.of("srihitha.txt"),
                                   "Srihitha ".repeat(200));
 
        Path zip = Path.of("students.zip");
        try (OutputStream file = Files.newOutputStream(zip);
             ZipOutputStream out = new ZipOutputStream(file)) {
            for (Path p : List.of(a, b)) {
                out.putNextEntry(new ZipEntry("students/" + p.getFileName()));
                Files.copy(p, out);
                out.closeEntry();
            }
        }
 
        long original = Files.size(a) + Files.size(b);
        System.out.println("Original: " + original + " bytes");
        System.out.println("Under a quarter of the size? "
            + (Files.size(zip) < original / 4));
    }
}
Output
Original: 3200 bytes
Under a quarter of the size? true

Explanation: Each file becomes an entry inside a students/ folder in the archive. Files.copy(path, out) writes the file's bytes into the current entry. The text repeats a lot, so the archive, including its headers, is less than a quarter of the original size.

The Checkpoint: Zip the 10 Largest Files

This tool walks a folder tree, finds the largest files, and zips them, keeping their folder structure. To keep the output short, it creates 15 sample files and zips the 3 largest.

ZipLargest.java▶ Try it
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
 
public class ZipLargest {
    static long size(Path p) {
        try {
            return Files.size(p);
        } catch (IOException e) {
            return 0;
        }
    }
 
    static List<Path> largest(Path root, int n) throws IOException {
        try (Stream<Path> files = Files.walk(root)) {
            return files.filter(Files::isRegularFile)
                        .sorted(Comparator.comparingLong(ZipLargest::size)
                                          .reversed())
                        .limit(n)
                        .toList();
        }
    }
 
    public static void main(String[] args) throws IOException {
        Path root = Path.of("data");
        for (int i = 1; i <= 15; i++) {
            Path dir = Files.createDirectories(root.resolve("part" + (i % 3)));
            Files.write(dir.resolve("file" + i + ".bin"), new byte[i * 100]);
        }
 
        List<Path> top = largest(root, 3);
        try (OutputStream file = Files.newOutputStream(Path.of("largest.zip"));
             ZipOutputStream zip = new ZipOutputStream(file)) {
            for (Path p : top) {
                String name = root.relativize(p).toString().replace('\\', '/');
                zip.putNextEntry(new ZipEntry(name));
                Files.copy(p, zip);
                zip.closeEntry();
                System.out.println("Zipped " + name
                    + " (" + size(p) + " bytes)");
            }
        }
    }
}
Output
Zipped part0/file15.bin (1500 bytes)
Zipped part2/file14.bin (1400 bytes)
Zipped part1/file13.bin (1300 bytes)

Explanation: Files.walk visits every file under data, the stream sorts them by size from largest to smallest, and limit(3) keeps the top three (use 10 for the real tool). Each is added to the zip with a name relative to data, so the folder structure is kept. replace('\\', '/') makes the names correct on Windows too.

Common Mistakes

Forgetting closeEntry(). The next entry may be written into the wrong place.

Using \ in entry names. The zip format uses /.

Zipping already-compressed files (JPG, MP4) and expecting big savings. They barely shrink.

Practice

  1. Easy: Zip three text files of your own into notes.zip.
  2. Harder: Write a method zipFolder(Path dir, Path zipFile) that adds every file in a folder tree, keeping relative paths.

Quick check: Creating zip files

4 questions
1Which class writes a zip archive?
2What must you call before writing each file's bytes?
3Which separator do zip entry names use?
4Which files compress well?

Key Takeaways

Was this tutorial helpful?

Lesson 363 of 482