Miré la biblioteca Zip predeterminada que viene con JDK y las librerías de compresión de Apache y no estoy satisfecho con ellas por 3 razones:
Están inflados y tienen un mal diseño de API. ¿Tengo que escribir 50 líneas de salida de matriz de bytes de placa de caldera, entrada zip, archivar flujos y cerrar flujos relevantes y detectar excepciones y mover búferes de bytes por mi cuenta ? ¿Por qué no puedo tener una API simple que se parezca a esta Zipper.unzip(InputStream zipFile, File targetDirectory, String password = null) y Zipper.zip(File targetDirectory, String password = null) que simplemente funcionen?
Parece que comprimir y descomprimir destruye los metadatos del archivo y el manejo de contraseñas no funciona.
Además, todas las bibliotecas que probé eran 2-3 veces más lentas en comparación con las herramientas zip de la línea de comandos que obtengo con UNIX.
Para mí (2) y (3) son puntos menores, pero realmente quiero una buena biblioteca probada con una interfaz de una línea.
Sé que es tarde y hay muchas respuestas, pero zip4j es una de las mejores bibliotecas 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:
<dependency> <groupId>net.lingala.zip4j</groupId> <artifactId>zip4j</artifactId> <version>1.3.2</version> </dependency>En Java 8, con IOUtils de Apache Commons-IO puede hacer esto:
try (java.util.zip.ZipFile zipFile = new ZipFile(file)) { 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(); try (InputStream in = zipFile.getInputStream(entry); OutputStream out = new FileOutputStream(entryDestination)) { IOUtils.copy(in, out); } } } }Todavía es un código repetitivo, pero solo tiene 1 dependencia no exótica: Commons-IO
En Java 11 y superior, es posible que haya mejores opciones disponibles, consulte el comentario de ZhekaKozlov.
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(); } } }