2009-06-02 8 views
8

Sto usando il seguente codice per estrarre un file zip in Java.Come estrarre le cartelle compresse in java?

import java.io.*; 
import java.util.zip.*; 

class testZipFiles 
{ 
    public static void main(String[] args) 
    { 

     try 
     { 
      String filename = "C:\\zip\\includes.zip"; 
      testZipFiles list = new testZipFiles(); 
      list.getZipFiles(filename); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    public void getZipFiles(String filename) 
    { 
     try 
     { 
      String destinationname = "c:\\zip\\"; 
      byte[] buf = new byte[1024]; 
      ZipInputStream zipinputstream = null; 
      ZipEntry zipentry; 
      zipinputstream = new ZipInputStream(
      new FileInputStream(filename)); 

      zipentry = zipinputstream.getNextEntry(); 
      while (zipentry != null) 
      { 
       //for each entry to be extracted 
       String entryName = zipentry.getName(); 
       System.out.println("entryname "+entryName); 
       int n; 
       FileOutputStream fileoutputstream; 
       File newFile = new File(entryName); 
       String directory = newFile.getParent(); 

       if(directory == null) 
       { 
        if(newFile.isDirectory()) 
        break; 
       } 

       fileoutputstream = new FileOutputStream(
        destinationname+entryName);    

       while ((n = zipinputstream.read(buf, 0, 1024)) > -1) 
        fileoutputstream.write(buf, 0, n); 

       fileoutputstream.close(); 
       zipinputstream.closeEntry(); 
       zipentry = zipinputstream.getNextEntry(); 

      }//while 

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

} 

Ovviamente questo non estrarrà un albero di cartelle a causa dell'istruzione break. Ho provato a usare la ricorsione per elaborare un albero delle cartelle ma non ci sono riuscito. Qualcuno potrebbe mostrarmi come migliorare questo codice per gestire un albero di cartelle invece di una cartella compressa a livello singolo.

+0

Chathuranga: la risposta di Emre ha risolto il problema? Se è così, grazie a lui controllando la sua risposta =) – mikek

risposta

7

È possibile utilizzare File.mkdirs() per creare cartelle. Provare a cambiare il vostro metodo come questo:

public static void getZipFiles(String filename) { 
    try { 
     String destinationname = "c:\\zip\\"; 
     byte[] buf = new byte[1024]; 
     ZipInputStream zipinputstream = null; 
     ZipEntry zipentry; 
     zipinputstream = new ZipInputStream(
       new FileInputStream(filename)); 

     zipentry = zipinputstream.getNextEntry(); 
     while (zipentry != null) { 
      //for each entry to be extracted 
      String entryName = destinationname + zipentry.getName(); 
      entryName = entryName.replace('/', File.separatorChar); 
      entryName = entryName.replace('\\', File.separatorChar); 
      System.out.println("entryname " + entryName); 
      int n; 
      FileOutputStream fileoutputstream; 
      File newFile = new File(entryName); 
      if (zipentry.isDirectory()) { 
       if (!newFile.mkdirs()) { 
        break; 
       } 
       zipentry = zipinputstream.getNextEntry(); 
       continue; 
      } 

      fileoutputstream = new FileOutputStream(entryName); 

      while ((n = zipinputstream.read(buf, 0, 1024)) > -1) { 
       fileoutputstream.write(buf, 0, n); 
      } 

      fileoutputstream.close(); 
      zipinputstream.closeEntry(); 
      zipentry = zipinputstream.getNextEntry(); 

     }//while 

     zipinputstream.close(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
+1

ZipEntry ha un metodo chiamato isDirectory(). Ciò dovrebbe semplificare il rilevamento delle voci della directory nell'archivio zip. –

+1

Potrebbe aver ragione. In javadoc di isDirectory() si dice "Una voce di directory è definita come il cui nome termina con un '/'". Ho modificato la mia risposta. – Emre

0

Un'altra opzione è commons-compress, per il quale esiste il codice di esempio sul sito linkato sopra.

0

Avevo bisogno di farlo a causa di un'API che stavo usando richiesto un parametro File, che non si può ottenere da una risorsa in un JAR.

Ho trovato che la risposta di @Emre non ha funzionato correttamente. Per qualche motivo ZipEntry ha saltato alcuni file nel JAR (nessun modello apparente a questo). Ho risolto questo problema utilizzando JarEntry. C'è anche un bug nel codice sopra, in cui il file nella voce zip potrebbe essere enumerato prima che la directory sia, il che causa un'eccezione perché la directory non è ancora stata creata.

Si noti che il codice seguente dipende dalle classi di utilità Apache Commons.

/** 
* 
* Extract a directory in a JAR on the classpath to an output folder. 
* 
* Note: User's responsibility to ensure that the files are actually in a JAR. 
* The way that I do this is to get the URI with 
*  URI url = getClass().getResource("/myresource").toURI(); 
* and then if url.isOpaque() we are in a JAR. There may be a more reliable 
* way however, please edit this answer if you know of one. 
* 
* @param classInJar A class in the JAR file which is on the classpath 
* @param resourceDirectory Path to resource directory in JAR 
* @param outputDirectory Directory to write to 
* @return String containing the path to the folder in the outputDirectory 
* @throws IOException 
*/ 
private static String extractDirectoryFromClasspathJAR(Class<?> classInJar, String resourceDirectory, String outputDirectory) 
     throws IOException { 

    resourceDirectory = StringUtils.strip(resourceDirectory, "\\/") + File.separator; 

    URL jar = classInJar.getProtectionDomain().getCodeSource().getLocation(); 
    //Note: If you want to extract from a named JAR, remove the above 
    //line and replace "jar.getFile()" below with the path to the JAR. 
    JarFile jarFile = new JarFile(new File(jar.getFile())); 

    byte[] buf = new byte[1024]; 
    Enumeration<JarEntry> jarEntries = jarFile.entries(); 
    while (jarEntries.hasMoreElements()) { 
     JarEntry jarEntry = jarEntries.nextElement(); 

     if (jarEntry.isDirectory() || !jarEntry.getName().startsWith(resourceDirectory)) { 
      continue;    
     } 


     String outputFileName = FilenameUtils.concat(outputDirectory, jarEntry.getName()); 
     //Create directories if they don't exist 
     new File(FilenameUtils.getFullPath(outputFileName)).mkdirs(); 

     //Write file 
     FileOutputStream fileOutputStream = new FileOutputStream(outputFileName); 
     int n; 
     InputStream is = jarFile.getInputStream(jarEntry); 
     while ((n = is.read(buf, 0, 1024)) > -1) { 
      fileOutputStream.write(buf, 0, n); 
     } 
     is.close(); 
     fileOutputStream.close(); 
    } 
    jarFile.close(); 

    String fullPath = FilenameUtils.concat(outputDirectory, resourceDirectory); 
    return fullPath; 
}