2009-06-02 62 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 2009-06-17 10:57:46

回答

7

您可以使用File.mkdirs()创建文件夹。试着改变你的方法是这样的:

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存档中目录条目的检测。 – 2009-06-02 11:49:02

0

另一种选择是commons-compress,为此,上面有链接的网站上的示例代码。

0

我需要这样做是因为我使用的API需要一个File参数,您无法从JAR中的资源获取该参数。

我发现@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; 
} 
相关问题