web-dev-qa-db-ger.com

Was ist eine gute Java Bibliothek, um Dateien zu komprimieren / entpacken?

Ich habe mir die Standard-Zip-Bibliothek angesehen, die mit den JDK- und Apache-Komprimierungsbibliotheken geliefert wird, und bin aus drei Gründen mit ihnen unzufrieden:

  1. Sie sind aufgebläht und haben ein schlechtes API-Design. Ich muss 50 Zeilen Kesselplatten-Byte-Array-Ausgabe schreiben, Zip-Eingabe, Streams ausfeilen und relevante Streams schließen und Ausnahmen abfangen und Byte-Puffer selbst verschieben ? Warum kann ich keine einfache API haben, die so aussieht: Zipper.unzip(InputStream zipFile, File targetDirectory, String password = null) und Zipper.Zip(File targetDirectory, String password = null), die einfach funktioniert?

  2. Es scheint, als würde das Zippen und Entpacken die Metadaten der Dateien zerstören und die Kennwortverarbeitung ist fehlerhaft.

  3. Außerdem waren alle Bibliotheken, die ich ausprobiert habe, 2-3x langsamer als die Kommandozeilen-Zip-Tools, die ich unter UNIX bekomme?

Für mich sind (2) und (3) kleinere Punkte, aber ich möchte wirklich eine gut getestete Bibliothek mit einer einzeiligen Schnittstelle.

213
pathikrit

Ich weiß, dass es spät ist und es gibt viele Antworten, aber dies Zip4j ist eine der besten Bibliotheken zum Zippen, die ich verwendet habe. Es ist einfach (kein Kesselcode) und kann leicht mit passwortgeschützten Dateien umgehen.

import net.lingala.Zip4j.exception.ZipException;
import net.lingala.Zip4j.core.ZipFile;


public static void unzip(){
    String source = "some/compressed/file.Zip";
    String destination = "some/destination/folder";
    String password = "password";

    try {
         ZipFile zipFile = new ZipFile(source);
         if (zipFile.isEncrypted()) {
            zipFile.setPassword(password);
         }
         zipFile.extractAll(destination);
    } catch (ZipException e) {
        e.printStackTrace();
    }
}

Die Maven-Abhängigkeit ist:

<dependency>
    <groupId>net.lingala.Zip4j</groupId>
    <artifactId>Zip4j</artifactId>
    <version>1.3.2</version>
</dependency>
274
user2003470

Mit Apache Commons-IO 's IOUtils können Sie dies tun:

Java.util.Zip.ZipFile zipFile = new ZipFile(file);
try {
  Enumeration<? extends ZipEntry> entries = zipFile.entries();
  while (entries.hasMoreElements()) {
    ZipEntry entry = entries.nextElement();
    File entryDestination = new File(outputDir,  entry.getName());
    if (entry.isDirectory()) {
        entryDestination.mkdirs();
    } else {
        entryDestination.getParentFile().mkdirs();
        InputStream in = zipFile.getInputStream(entry);
        OutputStream out = new FileOutputStream(entryDestination);
        IOUtils.copy(in, out);
        IOUtils.closeQuietly(in);
        out.close();
    }
  }
} finally {
  zipFile.close();
}

Es ist immer noch ein Boilerplate-Code, aber es gibt nur eine nicht-exotische Abhängigkeit: Commons-IO

70

Extrahieren Sie die Zip-Datei und alle zugehörigen Unterordner nur mit dem JDK:

private void extractFolder(String zipFile,String extractFolder) 
{
    try
    {
        int BUFFER = 2048;
        File file = new File(zipFile);

        ZipFile Zip = new ZipFile(file);
        String newPath = extractFolder;

        new File(newPath).mkdir();
        Enumeration zipFileEntries = Zip.entries();

        // Process each entry
        while (zipFileEntries.hasMoreElements())
        {
            // grab a Zip file entry
            ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
            String currentEntry = entry.getName();

            File destFile = new File(newPath, currentEntry);
            //destFile = new File(newPath, destFile.getName());
            File destinationParent = destFile.getParentFile();

            // create the parent directory structure if needed
            destinationParent.mkdirs();

            if (!entry.isDirectory())
            {
                BufferedInputStream is = new BufferedInputStream(Zip
                .getInputStream(entry));
                int currentByte;
                // establish buffer for writing file
                byte data[] = new byte[BUFFER];

                // write the current file to disk
                FileOutputStream fos = new FileOutputStream(destFile);
                BufferedOutputStream dest = new BufferedOutputStream(fos,
                BUFFER);

                // read and write until last byte is encountered
                while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
                    dest.write(data, 0, currentByte);
                }
                dest.flush();
                dest.close();
                is.close();
            }


        }
    }
    catch (Exception e) 
    {
        Log("ERROR: "+e.getMessage());
    }

}

ZIP-Dateien und alle zugehörigen Unterordner:

 private void addFolderToZip(File folder, ZipOutputStream Zip, String baseName) throws IOException {
    File[] files = folder.listFiles();
    for (File file : files) {
        if (file.isDirectory()) {
            addFolderToZip(file, Zip, baseName);
        } else {
            String name = file.getAbsolutePath().substring(baseName.length());
            ZipEntry zipEntry = new ZipEntry(name);
            Zip.putNextEntry(zipEntry);
            IOUtils.copy(new FileInputStream(file), Zip);
            Zip.closeEntry();
        }
    }
}
33

Eine weitere Option, die Sie auschecken können, ist zt-Zip auf der Maven-Zentral- und Projektseite unter https://github.com/zeroturnaround)/zt-Zip

Es verfügt über die Standardfunktionen zum Packen und Entpacken (auf Streams und im Dateisystem) sowie über zahlreiche Hilfsmethoden zum Testen auf Dateien in einem Archiv oder zum Hinzufügen/Entfernen von Einträgen.

22
toomasr

Vollständige Implementierung zum Komprimieren/Entpacken eines Ordners/einer Datei mit Zip4j


Laden Sie das Glas von hier und fügen Sie es hinz zu Ihrem Projekterstellungspfad herunter. Der class Balg kann jede Datei oder jeden Ordner mit oder ohne Passwortschutz komprimieren und extrahieren.

import Java.io.File;
import net.lingala.Zip4j.model.ZipParameters;
import net.lingala.Zip4j.util.Zip4jConstants;
import net.lingala.Zip4j.core.ZipFile;  

public class Compressor {
    public static void Zip(String targetPath, String destinationFilePath, String password) {
        try {
            ZipParameters parameters = new ZipParameters();
            parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
            parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);

            if(password.length()>0){
                parameters.setEncryptFiles(true);
                parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
                parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
                parameters.setPassword(password);
            }

            ZipFile zipFile = new ZipFile(destinationFilePath);

            File targetFile = new File(targetPath);
            if(targetFile.isFile()){
                zipFile.addFile(targetFile, parameters);
            }else if(targetFile.isDirectory()){
                zipFile.addFolder(targetFile, parameters);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void unzip(String targetZipFilePath, String destinationFolderPath, String password) {
        try {
            ZipFile zipFile = new ZipFile(targetZipFilePath);
            if (zipFile.isEncrypted()) {
                zipFile.setPassword(password);
            }
            zipFile.extractAll(destinationFolderPath);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**/ /// for test only
    public static void main(String[] args) {

        String targetPath = "target\\file\\or\\folder\\path";
        String zipFilePath = "Zip\\file\\Path"; 
        String unzippedFolderPath = "destination\\folder\\path";
        String password = "your_password"; // keep it EMPTY<""> for applying no password protection

        Compressor.Zip(targetPath, zipFilePath, password);
        Compressor.unzip(zipFilePath, unzippedFolderPath, password);
    }/**/
}
14
Minhas Kamal

Ein sehr schönes Projekt ist TrueZip .

TrueZIP ist ein Java basiertes Plug-In-Framework für virtuelle Dateisysteme (VFS), das einen transparenten Zugriff auf Archivdateien bietet, als wären es nur einfache Verzeichnisse

Zum Beispiel (von der Website ):

File file = new TFile("archive.tar.gz/README.TXT");
OutputStream out = new TFileOutputStream(file);
try {
   // Write archive entry contents here.
   ...
} finally {
   out.close();
}
7
Michael

Eine andere Option ist JZlib . Meiner Erfahrung nach ist es weniger "dateizentriert" als Zip4J. Wenn Sie also eher an speicherinternen Blobs als an Dateien arbeiten müssen, sollten Sie es sich ansehen.

Hier finden Sie ein vollständiges Beispiel für das rekursive Komprimieren und Dekomprimieren von Dateien: http://developer-tips.hubpages.com/hub/Zipping-and-Unzipping-Nested-Directories-in-Java-using -Apache-Commons-Compress

0
user1491819

Haben Sie sich http://commons.Apache.org/vfs/ angesehen? Es wird behauptet, viele Dinge für Sie zu vereinfachen. Aber ich habe es nie in einem Projekt verwendet.

Mir sind auch keine anderen Java-Native-Komprimierungsbibliotheken als das JDK oder die Apache-Komprimierung bekannt.

Ich erinnere mich, dass wir einige Funktionen aus Apache Ant herausgerissen haben - sie haben eine Menge Werkzeuge für die Komprimierung/Dekomprimierung eingebaut.

Beispielcode mit VFS würde folgendermaßen aussehen:

File zipFile = ...;
File outputDir = ...;
FileSystemManager fsm = VFS.getManager();
URI Zip = zipFile.toURI();
FileObject packFileObject = fsm.resolveFile(packLocation.toString());
FileObject to = fsm.toFileObject(destDir);
FileObject zipFS;
try {
    zipFS = fsm.createFileSystem(packFileObject);
    fsm.toFileObject(outputDir).copyFrom(zipFS, new AllFileSelector());
} finally {
    zipFS.close();
}
0
wemu