2009-06-02 2 views
8

다음 코드를 사용하여 Java에서 zip 파일을 추출합니다.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(); 
     } 
    } 

} 

분명히 break 문으로 인해 폴더 트리가 추출되지 않습니다. 재귀를 사용하여 폴더 트리를 처리하려고했지만 실패했습니다. 누군가가이 코드를 개선하여 압축 된 단일 레벨 폴더 대신 폴더 트리를 처리하는 방법을 보여줄 수 있습니까?

+0

Chathuranga : Emre의 대답으로 문제가 해결 되었습니까? 그렇다면 그의 대답을 확인해 주셔서 감사합니다 =) – mikek

답변

7

File.mkdirs()를 사용하여 폴더를 만들 수 있습니다. 이처럼 방법을 변경해보십시오 : 또 다른 옵션이있는 위의 링크 된 사이트의 샘플 코드가, commons-compress입니다

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에는 isDirectory()라는 메서드가 있습니다. 이렇게하면 zip 아카이브의 디렉토리 항목을 간단히 검색 할 수 있습니다. –

+1

당신이 옳을 수도 있습니다. isDirectory()의 javadoc에서 "디렉토리 항목은 '/'로 끝나는 이름으로 정의됩니다. 나는 내 대답을 편집했다. – Emre

0

JAR의 리소스에서 가져올 수없는 File 매개 변수가 필요한 API 때문에이 작업이 필요했습니다.

@Emre의 대답이 올바르게 작동하지 않는 것으로 나타났습니다. 웬일인지 ZipEntry는 JAR에서 몇 개의 파일을 건너 뛰었습니다. 대신 JarEntry를 사용하여이 문제를 해결했습니다. 위의 코드에는 디렉토리가 생성되기 전에 zip 항목의 파일을 열거 할 수있는 버그가 있습니다. 디렉토리가 아직 생성되지 않았기 때문에 예외가 발생합니다.

아래 코드는 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; 
} 
관련 문제