How to Decompress Files from a ZIP File in Java

Decompressing files from a ZIP file is a common task that can be performed using Java's java.util.zip package. This package provides the necessary classes to read and extract files from a ZIP archive. This blog post will guide you through the process of decompressing files from a ZIP file in Java.

Table of Contents

  1. Introduction
  2. Prerequisites
  3. Decompressing Files from a ZIP File
  4. Complete Example
  5. Conclusion

Introduction

Java provides robust support for handling ZIP files through the java.util.zip package. To decompress files from a ZIP file, you can use the ZipInputStream class to read the ZIP file and extract its entries. This tutorial will demonstrate how to use these classes to decompress files from a ZIP archive.

Prerequisites

Before you start, ensure you have the following:

  • A basic understanding of Java programming
  • A Java development environment (JDK and an IDE like IntelliJ IDEA or Eclipse)

Decompressing Files from a ZIP File

To decompress files from a ZIP file, you will:

  1. Create a ZipInputStream to read the ZIP file.
  2. Read each ZipEntry from the ZipInputStream.
  3. Extract the file data and write it to the appropriate location.
  4. Close the ZipEntry and ZipInputStream.

Example

The following example demonstrates how to decompress files from a ZIP file.

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.io.File;

public class UnzipFilesExample {
    public static void main(String[] args) {
        String zipFileName = "compressed.zip";
        String destDir = "output";

        File dir = new File(destDir);
        if (!dir.exists()) dir.mkdirs();

        try (FileInputStream fis = new FileInputStream(zipFileName);
             ZipInputStream zis = new ZipInputStream(fis)) {

            ZipEntry zipEntry = zis.getNextEntry();
            while (zipEntry != null) {
                File newFile = newFile(new File(destDir), zipEntry);
                if (zipEntry.isDirectory()) {
                    if (!newFile.isDirectory() && !newFile.mkdirs()) {
                        throw new IOException("Failed to create directory " + newFile);
                    }
                } else {
                    File parent = newFile.getParentFile();
                    if (!parent.isDirectory() && !parent.mkdirs()) {
                        throw new IOException("Failed to create directory " + parent);
                    }

                    try (FileOutputStream fos = new FileOutputStream(newFile)) {
                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = zis.read(buffer)) > 0) {
                            fos.write(buffer, 0, len);
                        }
                    }
                }
                zipEntry = zis.getNextEntry();
            }
            zis.closeEntry();
            System.out.println("Files decompressed successfully.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException {
        File destFile = new File(destinationDir, zipEntry.getName());

        String destDirPath = destinationDir.getCanonicalPath();
        String destFilePath = destFile.getCanonicalPath();

        if (!destFilePath.startsWith(destDirPath + File.separator)) {
            throw new IOException("Entry is outside of the target dir: " + zipEntry.getName());
        }

        return destFile;
    }
}

Explanation:

  • The zipFileName variable contains the name of the ZIP file to be decompressed.
  • The destDir variable specifies the destination directory where the files will be extracted.
  • The File object is created for the destination directory, and the mkdirs method is used to create the directory if it does not exist.
  • A FileInputStream is created to read the ZIP file.
  • A ZipInputStream is created to read the entries of the ZIP file.
  • The getNextEntry method is called to get the next ZipEntry from the ZipInputStream.
  • For each ZipEntry, a File object is created, and the directory structure is created if necessary.
  • The file data is read using a byte buffer and written to the new file using a FileOutputStream.
  • The try-with-resources statement ensures that the streams are closed automatically.

Complete Example

Here is the complete example, including all necessary classes and methods.

UnzipFilesExample.java

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.io.File;

public class UnzipFilesExample {
    public static void main(String[] args) {
        String zipFileName = "compressed.zip";
        String destDir = "output";

        File dir = new File(destDir);
        if (!dir.exists()) dir.mkdirs();

        try (FileInputStream fis = new FileInputStream(zipFileName);
             ZipInputStream zis = new ZipInputStream(fis)) {

            ZipEntry zipEntry = zis.getNextEntry();
            while (zipEntry != null) {
                File newFile = newFile(new File(destDir), zipEntry);
                if (zipEntry.isDirectory()) {
                    if (!newFile.isDirectory() && !newFile.mkdirs()) {
                        throw new IOException("Failed to create directory " + newFile);
                    }
                } else {
                    File parent = newFile.getParentFile();
                    if (!parent.isDirectory() && !parent.mkdirs()) {
                        throw new IOException("Failed to create directory " + parent);
                    }

                    try (FileOutputStream fos = new FileOutputStream(newFile)) {
                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = zis.read(buffer)) > 0) {
                            fos.write(buffer, 0, len);
                        }
                    }
                }
                zipEntry = zis.getNextEntry();
            }
            zis.closeEntry();
            System.out.println("Files decompressed successfully.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException {
        File destFile = new File(destinationDir, zipEntry.getName());

        String destDirPath = destinationDir.getCanonicalPath();
        String destFilePath = destFile.getCanonicalPath();

        if (!destFilePath.startsWith(destDirPath + File.separator)) {
            throw new IOException("Entry is outside of the target dir: " + zipEntry.getName());
        }

        return destFile;
    }
}

Conclusion

Decompressing files from a ZIP file in Java is a straightforward process using the java.util.zip package. By following the steps outlined in this tutorial, you can efficiently extract files from a ZIP archive. The example provided demonstrates how to read entries from a ZIP file and write the extracted data to the appropriate location.

Feel free to experiment with the code examples provided in this tutorial to gain a deeper understanding of how to decompress files in Java. Happy coding!

Comments