¿Qué es una buena biblioteca de Java para comprimir / descomprimir archivos?

Miré la biblioteca Zip predeterminada que viene con el JDK y las librerías de compresión de Apache y no estoy satisfecho con ellos por 3 razones:

  1. Están hinchados y tienen un diseño API malo. Tengo que escribir 50 líneas de salida de matriz de byte de placa de caldera, entrada de zip, flujo de salida de archivos y cerrar transmisiones relevantes y capturar excepciones y mover búferes de byte por mi cuenta . ¿Por qué no puedo tener una API simple que se parece a Zipper.unzip(InputStream zipFile, File targetDirectory, String password = null) y Zipper.zip(File targetDirectory, String password = null) que simplemente funciona?

  2. Parece que descomprimir la descompresión destruye los metadatos del archivo y el manejo de contraseñas está dañado.

  3. Además, todas las bibliotecas que probé eran 2-3 veces lentas en comparación con las herramientas de línea de comando que obtengo con UNIX.

Para mí (2) y (3) son puntos menores, pero realmente quiero una buena biblioteca probada con una interfaz de una sola línea.

Sé que es tarde y hay muchas respuestas, pero esta zip4j es una de las mejores librerías para comprimir que he usado. Es simple (sin código de caldera) y puede manejar fácilmente archivos protegidos con contraseña.

 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 dependencia de Maven es:

  net.lingala.zip4j zip4j 1.3.2  

Con IOUtils Apache Commons-IO puedes hacer esto:

 java.util.zip.ZipFile zipFile = new ZipFile(file); try { Enumeration 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(); } 

Sigue siendo un código repetitivo, pero solo tiene una dependencia no exótica: Commons-IO

Extraiga el archivo zip y todas sus subcarpetas, usando solo el 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()); } } 

Archivos zip y todas sus subcarpetas:

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

Otra opción que puede consultar es zt-zip disponible en la página central y de proyectos de Maven en https://github.com/zeroturnaround/zt-zip

Tiene la funcionalidad estándar de empaque y desembalaje (en las secuencias y en el sistema de archivos) + muchos métodos auxiliares para probar los archivos en un archivo o agregar / eliminar entradas.

Implementación completa para comprimir / descomprimir una carpeta / archivo con zip4j


Descargue el archivo desde aquí y agréguelo a la ruta de comstackción de su proyecto. La class abajo puede comprimir y extraer cualquier archivo o carpeta, con o sin contraseña.

 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); }/**/ } 

Un proyecto muy lindo es TrueZip .

TrueZIP es un marco de plugin basado en Java para sistemas de archivos virtuales (VFS) que proporciona acceso transparente a archivos de almacenamiento como si fueran simples directorios

Por ejemplo (desde el sitio web ):

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

Otra opción es JZlib . En mi experiencia, está menos “centrado en archivos” que zip4J, así que si necesitas trabajar en blobs en memoria en lugar de archivos, tal vez quieras echarle un vistazo.

Aquí hay un ejemplo completo para comprimir y descomprimir archivos recursivamente: http://developer-tips.hubpages.com/hub/Zipping-and-Unzipping-Nested-Directories-in-Java-using-Apache-Commons-Compress

¿Usted echó un vistazo a http://commons.apache.org/vfs/ ? Afirma que simplifica muchas cosas para ti. Pero nunca lo he usado en un proyecto.

Tampoco conozco las librerías de compresión Java-Native que no sean JDK o Apache Compression.

Recuerdo que una vez que arrancamos algunas funciones de Apache Ant, tienen muchas utilidades para compresión / descompresión integradas.

El código de muestra con VFS se vería así:

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