¿Cómo descomprimir archivos recursivamente en Java?

Tengo un archivo zip que contiene algunos otros archivos zip.

Por ejemplo, el archivo de correo es abc.zip y contiene xyz.zip , class1.java , class2.java . Y xyz.zip contiene el archivo class3.java y class4.java .

Así que necesito extraer el archivo zip usando Java a una carpeta que debe contener class1.java , class2.java , class3.java y class4.java .

Advertencia, el código aquí está bien para los archivos zip de confianza, no hay validación de ruta antes de la escritura que puede conducir a la vulnerabilidad de seguridad como se describe en zip-slip-vulnerabilidad si la usa para desinflar un archivo zip cargado desde un cliente desconocido.


Esta solución es muy similar a las soluciones anteriores ya publicadas, pero esta recrea la estructura de carpetas adecuada al descomprimir.

 static public void extractFolder(String zipFile) throws ZipException, IOException { System.out.println(zipFile); int BUFFER = 2048; File file = new File(zipFile); ZipFile zip = new ZipFile(file); String newPath = zipFile.substring(0, zipFile.length() - 4); 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(); } if (currentEntry.endsWith(".zip")) { // found a zip file, try to open extractFolder(destFile.getAbsolutePath()); } } } 

Aquí hay alguna base de código no probado en algún código viejo que tuve que descomprimir archivos.

 public void doUnzip(String inputZip, String destinationDirectory) throws IOException { int BUFFER = 2048; List zipFiles = new ArrayList(); File sourceZipFile = new File(inputZip); File unzipDestinationDirectory = new File(destinationDirectory); unzipDestinationDirectory.mkdir(); ZipFile zipFile; // Open Zip file for reading zipFile = new ZipFile(sourceZipFile, ZipFile.OPEN_READ); // Create an enumeration of the entries in the zip file Enumeration zipFileEntries = zipFile.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(unzipDestinationDirectory, currentEntry); destFile = new File(unzipDestinationDirectory, destFile.getName()); if (currentEntry.endsWith(".zip")) { zipFiles.add(destFile.getAbsolutePath()); } // grab file's parent directory structure File destinationParent = destFile.getParentFile(); // create the parent directory structure if needed destinationParent.mkdirs(); try { // extract file if not a directory if (!entry.isDirectory()) { BufferedInputStream is = new BufferedInputStream(zipFile.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 (IOException ioe) { ioe.printStackTrace(); } } zipFile.close(); for (Iterator iter = zipFiles.iterator(); iter.hasNext();) { String zipName = (String)iter.next(); doUnzip( zipName, destinationDirectory + File.separatorChar + zipName.substring(0,zipName.lastIndexOf(".zip")) ); } } 

Tomo ca.anderson4 y elimino List ZipFiles y reescribo un poco, esto es lo que obtuve:

 public class Unzip { public void unzip(String zipFile) throws ZipException, IOException { System.out.println(zipFile);; int BUFFER = 2048; File file = new File(zipFile); ZipFile zip = new ZipFile(file); String newPath = zipFile.substring(0, zipFile.length() - 4); 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(); } if (currentEntry.endsWith(".zip")) { // found a zip file, try to open unzip(destFile.getAbsolutePath()); } } } public static void main(String[] args) { Unzip unzipper=new Unzip(); try { unzipper.unzip("test/test.zip"); } catch (ZipException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 

Probé y funciona

En las pruebas noté que File.mkDirs () no funciona en Windows …

/ ** * para un nombre de ruta completo dado recrea todos los directorios principales ** /

  private void createParentHierarchy(String parentName) throws IOException { File parent = new File(parentName); String[] parentsStrArr = parent.getAbsolutePath().split(File.separator == "/" ? "/" : "\\\\"); //create the parents of the parent for(int i=0; i < parentsStrArr.length; i++){ StringBuffer currParentPath = new StringBuffer(); for(int j = 0; j < i; j++){ currParentPath.append(parentsStrArr[j]+File.separator); } File currParent = new File(currParentPath.toString()); if(!currParent.isDirectory()){ boolean created = currParent.mkdir(); if(isVerbose)log("creating directory "+currParent.getAbsolutePath()); } } //create the parent itself if(!parent.isDirectory()){ boolean success = parent.mkdir(); } } 

Uno debe CERRAR archivo zip después de descomprimir.

 static public void extractFolder(String zipFile) throws ZipException, IOException { System.out.println(zipFile); int BUFFER = 2048; File file = new File(zipFile); ZipFile zip = new ZipFile(file); try { ...code from other answers ( ex. NeilMonday )... } finally { zip.close(); } } 

Modificado como lo necesitaba, mezclé algunas de las mejores respuestas. Esta versión:

  • Extracto recursivo de un zip a una ubicación determinada

  • Crear directorios vacíos

  • Cierre el cierre correctamente


 public static void unZipAll(File source, File destination) throws IOException { System.out.println("Unzipping - " + source.getName()); int BUFFER = 2048; ZipFile zip = new ZipFile(source); try{ destination.getParentFile().mkdirs(); 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(destination, 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 = null; FileOutputStream fos = null; BufferedOutputStream dest = null; try{ is = new BufferedInputStream(zip.getInputStream(entry)); int currentByte; // establish buffer for writing file byte data[] = new byte[BUFFER]; // write the current file to disk fos = new FileOutputStream(destFile); 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); } } catch (Exception e){ System.out.println("unable to extract entry:" + entry.getName()); throw e; } finally{ if (dest != null){ dest.close(); } if (fos != null){ fos.close(); } if (is != null){ is.close(); } } }else{ //Create directory destFile.mkdirs(); } if (currentEntry.endsWith(".zip")) { // found a zip file, try to extract unZipAll(destFile, destinationParent); if(!destFile.delete()){ System.out.println("Could not delete zip"); } } } } catch(Exception e){ e.printStackTrace(); System.out.println("Failed to successfully unzip:" + source.getName()); } finally { zip.close(); } System.out.println("Done Unzipping:" + source.getName()); } 

Igual que la respuesta de NeilMonday, pero extrae directorios vacíos:

 static public void extractFolder(String zipFile) throws ZipException, IOException { System.out.println(zipFile); int BUFFER = 2048; File file = new File(zipFile); ZipFile zip = new ZipFile(file); String newPath = zipFile.substring(0, zipFile.length() - 4); 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(); } else{ destFile.mkdirs() } if (currentEntry.endsWith(".zip")) { // found a zip file, try to open extractFolder(destFile.getAbsolutePath()); } } } 
 File dir = new File("BASE DIRECTORY PATH"); FileFilter ff = new FileFilter() { @Override public boolean accept(File f) { //only want zip files return (f.isFile() && f.getName().toLowerCase().endsWith(".zip")); } }; File[] list = null; while ((list = dir.listFiles(ff)).length > 0) { File file1 = list[0]; //TODO unzip the file to the base directory }