2009-06-02 12 views
8

Korzystam z następującego kodu, aby wypakować plik zip w Javie.Jak wyodrębnić skompresowane foldery w 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(); 
     } 
    } 

} 

Oczywiście nie wyodrębni to drzewa folderów ze względu na instrukcję break. Próbowałem użyć rekursji do przetworzenia drzewa folderów, ale nie udało się. Czy ktoś mógłby mi pokazać, jak poprawić ten kod, aby obsłużyć drzewo folderów zamiast skompresowanego folderu z pojedynczym poziomem.

+0

Chathuranga: Czy odpowiedź Emre rozwiązała twój problem? Jeśli tak, podziękuj mu, sprawdzając jego odpowiedź =) – mikek

Odpowiedz

7

Możesz użyć File.mkdirs() do tworzenia folderów. Spróbuj zmienić metodę tak:

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 ma metodę o nazwie isDirectory(). To powinno uprościć wykrywanie wpisów do katalogu w archiwum zip. –

+1

Może masz rację. W javadoc z isDirectory() jest napisane: "Pozycja katalogu jest zdefiniowana jako ta, której nazwa kończy się na"/"". Edytowałem swoją odpowiedź. – Emre

0

Inną opcją jest commons-compress, dla których istnieje przykładowy kod na stronie związanej powyżej.

0

Potrzebowałem zrobić to z powodu interfejsu API, którego używałem, wymaganego parametru pliku, którego nie można uzyskać z zasobu w pliku JAR.

Znalazłem, że odpowiedź @Emre nie działa poprawnie. Z jakiegoś powodu ZipEntry pominął kilka plików w JAR (bez widocznego wzoru). Naprawiłem to, używając zamiast tego JarEntry. Istnieje również błąd w powyższym kodzie, w którym plik w pozycji zip może być wyliczony przed katalogiem, co powoduje wyjątek, ponieważ katalog nie został jeszcze utworzony.

Należy zauważyć, że poniższy kod zależy od klas użytkowych 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; 
} 
Powiązane problemy