web-dev-qa-db-fra.com

Qu'est-ce qu'une bonne bibliothèque Java pour compresser / décompresser des fichiers?

J'ai examiné la bibliothèque Zip par défaut fournie avec le JDK et les bibliothèques de compression Apache et je ne suis pas satisfait de celles-ci pour trois raisons:

  1. Ils sont gonflés et ont une mauvaise conception API. Je dois écrire 50 lignes de sortie du tableau d'octets de la plaque de la chaudière, entrée Zip, archiver les flux et fermer les flux pertinents, intercepter les exceptions et déplacer les tampons octets par moi-même ? Pourquoi est-ce que je ne peux pas avoir une API simple qui ressemble à ceci Zipper.unzip(InputStream zipFile, File targetDirectory, String password = null) et Zipper.Zip(File targetDirectory, String password = null) qui fonctionne?

  2. Il semble que la décompression zippée détruit les méta-données du fichier et que la gestion du mot de passe est rompue.

  3. En outre, toutes les bibliothèques que j'ai essayées étaient 2-3x lentes par rapport aux outils Zip en ligne de commande que je reçois avec UNIX?

Pour moi (2) et (3) sont des points mineurs, mais je veux vraiment une bonne bibliothèque testée avec une interface à une ligne.

213
pathikrit

Je sais qu'il est tard et qu'il y a beaucoup de réponses, mais ceci Zip4j est l'une des meilleures bibliothèques que j'ai utilisées pour la compression. C'est simple (pas de code de la chaudière) et peut facilement gérer les fichiers protégés par mot de passe.

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

La dépendance Maven est:

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

Avec Apache Commons-IOIOUtils , vous pouvez le faire:

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

C'est encore du code standard, mais il n'a qu'une dépendance non-exotique: Commons-IO

70
Geoffrey De Smet

Extrayez le fichier Zip et tous ses sous-dossiers en utilisant uniquement le 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());
    }

}

Fichiers Zip et tous ses sous-dossiers:

 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
Bashir Beikzadeh

Une autre option que vous pouvez vérifier est zt-Zip disponible sur la page centrale de Maven et sur la page du projet sous https://github.com/zeroturnaround/zt-Zip

Il dispose des fonctionnalités standard d'emballage et de décompression (sur les flux et sur le système de fichiers) + de nombreuses méthodes auxiliaires pour tester les fichiers dans une archive ou ajouter/supprimer des entrées.

22
toomasr

Mise en œuvre complète pour compresser/décompresser un dossier/fichier avec Zip4j


Téléchargez le fichier jar de ici , et ajoutez-le à votre chemin de génération de projet. Le class ci-dessous peut compresser et extraire n’importe quel fichier ou dossier, avec ou sans protection par mot de passe.

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

Un très beau projet est TrueZip .

TrueZIP est un framework de plug-in basé sur Java pour les systèmes de fichiers virtuels (VFS) qui fournit un accès transparent aux fichiers d’archives comme s’il s’agissait simplement de répertoires simples.

Par exemple (à partir du site web ):

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

Une autre option est JZlib . D'après mon expérience, il est moins "centré sur les fichiers" que Zip4J. Par conséquent, si vous devez travailler sur des objets blobs en mémoire plutôt que sur des fichiers, vous voudrez peut-être y jeter un coup d'œil.

2

Il existe un exemple complet ici pour compresser et décompresser des fichiers récursivement: http://developer-tips.hubpages.com/hub/Zipping-and-Unzipping-Nested-Directories-in-Java-using-Apache-Commons- Compresser

0
user1491819

Avez-vous jeté un œil à http://commons.Apache.org/vfs/ ? Il prétend simplifier beaucoup de choses pour vous. Mais je ne l'ai jamais utilisé dans un projet.

Je ne connais pas non plus les bibliothèques de compression Java-Native autres que JDK ou Apache Compression.

Je me souviens qu'une fois, nous avons extrait certaines fonctionnalités d'Apache Ant - elles ont beaucoup d'utilitaires de compression/décompression intégrés.

Un exemple de code avec VFS ressemblerait à ceci:

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