Zippen und Entpacken in Java

1. Übersicht

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 Pakets java.util.zip , in dem alle Dienstprogramme zum Komprimieren und Entpacken aufgeführt sind.

2. Zippen Sie eine Datei

Schauen wir uns zunächst eine einfache Operation an - das Komprimieren einer einzelnen Datei.

In unserem Beispiel hier komprimieren wir eine Datei mit dem Namen test1.txt in ein Archiv mit dem Namen compress.zip .

Wir werden natürlich zuerst von der Festplatte auf die Datei zugreifen - schauen wir uns das an:

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 werden test1.txt und test2.txt in multiCompressed.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. Komprimieren Sie ein Verzeichnis

Lassen Sie uns nun diskutieren, wie ein ganzes Verzeichnis komprimiert wird. Wir werden zipTest in dirCompressed.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 ZipEntry- Namen der Nachkommen an, um die Hierarchie zu speichern.
  • Wir erstellen auch einen Verzeichniseintrag für jedes leere Verzeichnis

5. Entpacken Sie ein Archiv

Lassen Sie uns nun ein Archiv entpacken und dessen Inhalt extrahieren.

In diesem Beispiel entpacken wir compress.zip in einen neuen Ordner mit dem Namen unzipTest .

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) { // ... } zis.closeEntry(); zis.close(); } }

Innerhalb der while- Schleife durchlaufen wir jeden ZipEntry und prüfen zunächst, ob es sich um ein Verzeichnis handelt . Wenn dies der Fall ist, erstellen wir das Verzeichnis mit der Methode mkdirs () . Andernfalls fahren wir mit der Erstellung der Datei fort:

while (zipEntry != null) { File newFile = newFile(destDir, zipEntry); if (zipEntry.isDirectory()) { if (!newFile.isDirectory() && !newFile.mkdirs()) { throw new IOException("Failed to create directory " + newFile); } } else { // fix for Windows-created archives File parent = newFile.getParentFile(); if (!parent.isDirectory() && !parent.mkdirs()) { throw new IOException("Failed to create directory " + parent); } // write file content FileOutputStream fos = new FileOutputStream(newFile); int len; while ((len = zis.read(buffer)) > 0) { fos.write(buffer, 0, len); } fos.close(); } zipEntry = zis.getNextEntry(); }

Ein Hinweis hier ist, dass wir im Zweig else zuerst prüfen, ob das übergeordnete Verzeichnis der Datei vorhanden ist. Dies ist für unter Windows erstellte Archive erforderlich, in denen die Stammverzeichnisse keinen entsprechenden Eintrag in der Zip-Datei haben.

Ein weiterer wichtiger Punkt ist die newFile () -Methode:

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

Diese Methode schützt vor dem Schreiben von Dateien in das Dateisystem außerhalb des Zielordners. Diese Sicherheitsanfälligkeit heißt Zip Slip und Sie können hier mehr darüber lesen.

6. Fazit

Dieses Tutorial zeigt, wie wir Java-Bibliotheken zum Komprimieren und Entpacken von Dateien verwenden können.

Die Implementierung dieser Beispiele finden Sie auf GitHub.