BackendBench
Coffee

Unravel โ€บ Java concepts โ€บ I/O and files

I/O and data

ZIP and GZIP compression

GZIPOutputStream compresses a single stream; ZipOutputStream bundles many named entries into one archive.

Learn these first

At a glance

Mental model

GZIP is a vacuum bag for one item.

What happens, in order
  1. 1Compress: try (GZIPOutputStream out = new GZIPOutputStream(new FileOutputStream("a.gz"))) { out.write(bytes); }Decompress by wrapping a GZIPInputStream around the input.
  2. 2ZIP: zip.putNextEntry(new ZipEntry("dir/file.txt")), write bytes, zip.closeEntry()Read with ZipInputStream.getNextEntry() in a loop, or open random entries with ZipFile.
  3. 3Close the outermost stream: it writes the trailer (checksum, directory) that makes the file validAn unclosed GZIP stream produces a truncated file.
  4. 4Always close in try-with-resources; large data should be copied with transferTo rather than loaded into memory
Remember
Watch out
Not closing the output stream, giving a corrupt fileExtracting entry names without checking the path (zip slip)Reading an entire archive into memory
Example (highlighted lines explain it)
import java.io.*;import java.nio.file.*;import java.util.zip.*;public class Unpack {  static void extract(Path zip, Path dest) throws IOException {    try (ZipInputStream in = new ZipInputStream(Files.newInputStream(zip))) {      ZipEntry e;      while ((e = in.getNextEntry()) != null) {        Path out = dest.resolve(e.getName()).normalize();        if (!out.startsWith(dest)) throw new IOException("bad entry " + e.getName());        if (!e.isDirectory()) Files.copy(in, out, StandardCopyOption.REPLACE_EXISTING);      }    }  }  static byte[] gzip(byte[] data) throws IOException {    ByteArrayOutputStream bytes = new ByteArrayOutputStream();    try (GZIPOutputStream gz = new GZIPOutputStream(bytes)) { gz.write(data); }    return bytes.toByteArray();  }}
  1. line 6 uses ZipInputStream, the core of ZIP and GZIP compression
  2. line 7 uses ZipEntry, the core of ZIP and GZIP compression
  3. line 17 uses GZIPOutputStream, the core of ZIP and GZIP compression
Read the full explanation (about 1 min)

GZIPOutputStream compresses a single stream; ZipOutputStream bundles many named entries into one archive. You wrap them around ordinary streams.

A mental model

GZIP is a vacuum bag for one item. ZIP is a suitcase with labelled compartments, each compartment packed in its own vacuum bag.

How it works

Compress: try (GZIPOutputStream out = new GZIPOutputStream(new FileOutputStream("a.gz"))) { out.write(bytes); }. Decompress by wrapping a GZIPInputStream around the input.

ZIP: zip.putNextEntry(new ZipEntry("dir/file.txt")), write bytes, zip.closeEntry(). Read with ZipInputStream.getNextEntry() in a loop, or open random entries with ZipFile.

Close the outermost stream: it writes the trailer (checksum, directory) that makes the file valid. An unclosed GZIP stream produces a truncated file.

Always close in try-with-resources; large data should be copied with transferTo rather than loaded into memory.

Going deeper

Zip slip: an entry named ../../etc/cron.d/x extracted naively overwrites files outside the target folder. Resolve each entry against the destination and check it stays inside.

Zip bombs: a tiny archive can expand to terabytes. Count the extracted bytes and entries and stop at a limit.

HTTP responses with Content-Encoding: gzip are usually decompressed for you by the HTTP client; compress only what is large and compressible (text, JSON), not images or already-compressed data.

Under the hood

Both use the DEFLATE algorithm through java.util.zip.Deflater and Inflater, which call the zlib native library. ZipFile reads the central directory at the end of the file for random access, while ZipInputStream reads entries in order.

Common mistakes

  • Not closing the output stream, giving a corrupt file.
  • Extracting entry names without checking the path (zip slip).
  • Reading an entire archive into memory.

How Unravel recognises it

When you paste code, Unravel looks for these signs of zip and gzip compression. Spotting them yourself is a good habit when you read unfamiliar code:

Part of a learning path

Related concepts

Frequently asked questions

What is ZIP and GZIP compression?

GZIPOutputStream compresses a single stream; ZipOutputStream bundles many named entries into one archive. You wrap them around ordinary streams.

What are the most common mistakes with ZIP and GZIP compression?

Not closing the output stream, giving a corrupt file. Extracting entry names without checking the path (zip slip). Reading an entire archive into memory.

How can I see ZIP and GZIP compression in real code?

Paste your own Java into Unravel and it will point out where zip and gzip compression appears, explain how it works at the detail level you choose, and draw the flow of the code around it.