2009-06-02 7 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

これは、私が使用していたAPIがJARのリソースから取得できないFileパラメータを必要とするために必要でした。

@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; 
}