Zippen und Entpacken in Java

Komprimieren und Entpacken in Java

1. Überblick

In diesem kurzen Tutorial erfahren Sie, wie Sie eine Datei in ein Archiv komprimieren und das Archiv entpacken - alles unter Verwendung der von Java bereitgestellten Kernbibliotheken.

Diese Kernbibliotheken sind Teil des Paketsjava.util.zip, in dem wir alle Dienstprogramme zum Komprimieren und Entpacken finden.

2. Zip eine Datei

Schauen wir uns zunächst einen einfachen Vorgang an - das Komprimieren einer einzelnen Datei.

In unserem Beispiel hier komprimieren wir eine Datei mit dem Namentest1.txt in eine archivierte Datei mit dem Namencompressed.zip. __

Wir werden natürlich zuerst von der Festplatte auf die Datei zugreifen - werfen wir einen Blick darauf:

public class ZipFile {
    public static void main(String[] args) throws IOException {
        String sourceFile = "test1.txt";
        FileOutputStream fos = new FileOutputStream("compressed.zip");
        ZipOutputStream zipOut = new ZipOutputStream(fos);
        File fileToZip = new File(sourceFile);
        FileInputStream fis = new FileInputStream(fileToZip);
        ZipEntry zipEntry = new ZipEntry(fileToZip.getName());
        zipOut.putNextEntry(zipEntry);
        byte[] bytes = new byte[1024];
        int length;
        while((length = fis.read(bytes)) >= 0) {
            zipOut.write(bytes, 0, length);
        }
        zipOut.close();
        fis.close();
        fos.close();
    }
}

3. Mehrere Dateien komprimieren

Als Nächstes sehen wir uns an, wie Sie mehrere Dateien in eine Zip-Datei komprimieren. Wir werdentest1.txt undtest2.txt inmultiCompressed.zip komprimieren:

public class ZipMultipleFiles {
    public static void main(String[] args) throws IOException {
        List srcFiles = Arrays.asList("test1.txt", "test2.txt");
        FileOutputStream fos = new FileOutputStream("multiCompressed.zip");
        ZipOutputStream zipOut = new ZipOutputStream(fos);
        for (String srcFile : srcFiles) {
            File fileToZip = new File(srcFile);
            FileInputStream fis = new FileInputStream(fileToZip);
            ZipEntry zipEntry = new ZipEntry(fileToZip.getName());
            zipOut.putNextEntry(zipEntry);

            byte[] bytes = new byte[1024];
            int length;
            while((length = fis.read(bytes)) >= 0) {
                zipOut.write(bytes, 0, length);
            }
            fis.close();
        }
        zipOut.close();
        fos.close();
    }
}

4. Zip ein Verzeichnis

Lassen Sie uns nun diskutieren, wie Sie ein gesamtes Verzeichnis komprimieren. Wir werdenzipTest indirCompressed.zip verzeichnen:

public class ZipDirectory {
    public static void main(String[] args) throws IOException {
        String sourceFile = "zipTest";
        FileOutputStream fos = new FileOutputStream("dirCompressed.zip");
        ZipOutputStream zipOut = new ZipOutputStream(fos);
        File fileToZip = new File(sourceFile);

        zipFile(fileToZip, fileToZip.getName(), zipOut);
        zipOut.close();
        fos.close();
    }

    private static void zipFile(File fileToZip, String fileName, ZipOutputStream zipOut) throws IOException {
        if (fileToZip.isHidden()) {
            return;
        }
        if (fileToZip.isDirectory()) {
            if (fileName.endsWith("/")) {
                zipOut.putNextEntry(new ZipEntry(fileName));
                zipOut.closeEntry();
            } else {
                zipOut.putNextEntry(new ZipEntry(fileName + "/"));
                zipOut.closeEntry();
            }
            File[] children = fileToZip.listFiles();
            for (File childFile : children) {
                zipFile(childFile, fileName + "/" + childFile.getName(), zipOut);
            }
            return;
        }
        FileInputStream fis = new FileInputStream(fileToZip);
        ZipEntry zipEntry = new ZipEntry(fileName);
        zipOut.putNextEntry(zipEntry);
        byte[] bytes = new byte[1024];
        int length;
        while ((length = fis.read(bytes)) >= 0) {
            zipOut.write(bytes, 0, length);
        }
        fis.close();
    }
}

Beachten Sie, dass:

  • Um Unterverzeichnisse zu komprimieren, durchlaufen wir sie rekursiv.

  • Jedes Mal, wenn wir ein Verzeichnis finden, hängen wir seinen Namen an den Namen des NachkommenZipEntryan, um die Hierarchie zu speichern.

  • Wir erstellen auch einen Verzeichniseintrag für jedes leere Verzeichnis

5. Entpacke ein Archiv

Entpacken wir nun ein Archiv und extrahieren dessen Inhalt.

In diesem Beispiel entpacken wircompressed.zip in einen neuen Ordner mit dem NamenunzipTest.

Werfen wir einen Blick:

public class UnzipFile {
    public static void main(String[] args) throws IOException {
        String fileZip = "src/main/resources/unzipTest/compressed.zip";
        File destDir = new File("src/main/resources/unzipTest");
        byte[] buffer = new byte[1024];
        ZipInputStream zis = new ZipInputStream(new FileInputStream(fileZip));
        ZipEntry zipEntry = zis.getNextEntry();
        while (zipEntry != null) {
            File newFile = newFile(destDir, zipEntry);
            FileOutputStream fos = new FileOutputStream(newFile);
            int len;
            while ((len = zis.read(buffer)) > 0) {
                fos.write(buffer, 0, len);
            }
            fos.close();
            zipEntry = zis.getNextEntry();
        }
        zis.closeEntry();
        zis.close();
    }

    public 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;
    }
}

Ein weiterer wichtiger Punkt ist die MethodenewFile(). Diese Methode schützt vor dem Schreiben von Dateien in das Dateisystem außerhalb des Zielordners. Diese Sicherheitsanfälligkeit wird als Zip Slip bezeichnet und Sie könnenread more about it here.

6. Fazit

Dieses Tutorial zeigt, wie einfach die Verwendung von Java-Bibliotheken zum Komprimieren und Dekomprimieren von Dateien ist.

Die Implementierung dieser Beispiele findet sich inover on GitHub - dies ist ein Maven-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein, wie es ist.