javabeginner

ZIP Compression and Extraction

Compress and extract ZIP archives in Java using ZipOutputStream and ZipInputStream with directory support.

java
import java.io.*;
import java.nio.file.*;
import java.util.zip.*;

public class ZipUtil {

    // Compress files into a ZIP
    public static void zip(String zipFile, String... sourcePaths) throws IOException {
        try (var zos = new ZipOutputStream(new FileOutputStream(zipFile))) {
            for (String src : sourcePaths) {
                Path sourcePath = Path.of(src);
                if (Files.isDirectory(sourcePath)) {
                    zipDirectory(sourcePath, sourcePath.getFileName().toString(), zos);
                } else {
                    zipFile(sourcePath, sourcePath.getFileName().toString(), zos);
                }
            }
        }
        System.out.println("Created: " + zipFile);
    }

    private static void zipDirectory(Path dir, String base, ZipOutputStream zos)
            throws IOException {
        try (var stream = Files.walk(dir)) {
            stream.forEach(path -> {
                try {
                    String entryName = base + "/" + dir.relativize(path);
                    if (Files.isDirectory(path)) {
                        zos.putNextEntry(new ZipEntry(entryName + "/"));
                    } else {
                        zipFile(path, entryName, zos);
                    }
                } catch (IOException e) {
                    throw new UncheckedIOException(e);
                }
            });
        }
    }

    private static void zipFile(Path file, String entryName, ZipOutputStream zos)
            throws IOException {
        zos.putNextEntry(new ZipEntry(entryName));
        Files.copy(file, zos);
        zos.closeEntry();
    }

    // Extract ZIP
    public static void unzip(String zipFile, String destDir) throws IOException {
        Path dest = Path.of(destDir);
        try (var zis = new ZipInputStream(new FileInputStream(zipFile))) {
            ZipEntry entry;
            while ((entry = zis.getNextEntry()) != null) {
                Path outPath = dest.resolve(entry.getName()).normalize();

                // Prevent zip-slip (path traversal)
                if (!outPath.startsWith(dest)) {
                    throw new IOException("Zip slip: " + entry.getName());
                }

                if (entry.isDirectory()) {
                    Files.createDirectories(outPath);
                } else {
                    Files.createDirectories(outPath.getParent());
                    Files.copy(zis, outPath, StandardCopyOption.REPLACE_EXISTING);
                }
                zis.closeEntry();
            }
        }
        System.out.println("Extracted to: " + destDir);
    }

    public static void main(String[] args) throws IOException {
        zip("archive.zip", "src", "README.md");
        unzip("archive.zip", "output");
    }
}

Use Cases

  • Creating ZIP archives for file downloads
  • Extracting uploaded ZIP files safely
  • Data backup and packaging utilities

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.