2016-02-11 64 views
6

我知道Oracle注意到ZIP/GZIP文件壓縮器/解壓縮器方法on their website。但我有一個場景,我需要掃描並確定是否包含任何嵌套的ZIP/RAR。例如,下面的情況:用於嵌套ZIP文件處理的Java實用程序庫

-MyFiles.zip 
    -MyNestedFiles.zip 
     -MyMoreNestedFiles.zip 
      -MoreProbably.zip 
     -Other_non_zips 
    -Other_non_zips 
-Other_non_zips 

我知道Apache的百科全書壓縮包和java.util.zip是wideley使用的包,其中公共壓縮實際上迎合的java.util.zip例如缺少的功能一些字符設置,同時做拉鍊。但我不確定的是通過嵌套zip文件進行遞歸的實用程序,SO上提供的答案並不是很好的例子。我嘗試下面的代碼(這是我從甲骨文博客了),但我懷疑,嵌套目錄遞歸,因爲它根本無法找到文件失敗:

public static void processZipFiles(String pathName) throws Exception{ 
     ZipInputStream zis = null; 
     InputStream is = null; 
     try { 
      ZipFile zipFile = new ZipFile(new File(pathName)); 
      String nestPathPrefix = zipFile.getName().substring(0, zipFile.getName().length() -4); 
      for(Enumeration e = zipFile.entries(); e.hasMoreElements();){ 
      ZipEntry ze = (ZipEntry)e.nextElement(); 
      if(ze.getName().contains(".zip")){ 
       is = zipFile.getInputStream(ze); 
       zis = new ZipInputStream(is); 
       ZipEntry zentry = zis.getNextEntry(); 

       while (zentry!=null){ 
        System.out.println(zentry.getName()); 
        zentry = zis.getNextEntry(); 
        ZipFile nestFile = new ZipFile(nestPathPrefix+"\\"+zentry.getName()); 
        if (zentry.getName().contains(".zip")) { 
         processZipFiles(nestPathPrefix+"\\"+zentry.getName()); 
        } 
       } 
       is.close(); 
      } 
      } 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally{ 
      if(is != null) 
       is.close(); 
      if(zis!=null) 
       zis.close(); 
     } 
    } 

可能是我做錯了什麼 - 或者使用錯誤的使用情況。我的目標是確定是否有任何文件或嵌套的zip文件有我不允許的文件擴展名。這是爲了確保我可以阻止我的用戶上傳禁止的文件,即使他們正在壓縮文件。我也可以選擇使用可以進行遞歸分析的Tika(使用Zukka Zitting的解決方案),但我不確定我是否可以使用元數據來執行此檢測。

任何幫助/建議表示讚賞。

+0

你不應該從外部zip條目的輸入流打開Nested Zip,而不是通過文件名(這不會因爲文件在zip中不在文件系統中)而被打開? – Gagravarr

回答

2

使用共享壓縮會更容易些,這不僅是因爲它有不同的解壓縮它使生活更輕鬆+允許處理的其它的壓縮格式(例如焦油)在同一時間

如果你想之間的合理共享界面只使用內置的ZIP支持,我建議你做這樣的事情:

File file = new File("outermost.zip"); 
FileInputStream input = new FileInputStream(file); 
check(input, file.toString()); 

public static void check(InputStream compressedInput, String name) { 
    ZipInputStream input = new ZipInputStream(compressedInput); 
    ZipEntry entry = null; 
    while ((entry = input.getNextEntry()) != null) { 
     System.out.println("Found " + entry.getName() + " in " + name); 
     if (entry.getName().endsWith(".zip")) { // TODO Better checking 
     check(input, name + "/" + entry.getName()); 
     } 
    } 
} 

您的代碼將失敗,因爲你試圖內outer.zipinner.zip爲本地文件,但它不」 t作爲獨立文件存在。上面的代碼將處理事情.zip另一個zip文件結束,而將遞歸

你可能想使用公共壓縮的,所以你可以處理文件名交替的東西,其他的壓縮格式等

+0

這是一個簡單的解決方案,但不通過.RAR遞歸。我嘗試了Tika,但解析元數據需要很長時間(可能是因爲它解析了整個事物)。 – ha9u63ar

+0

我可以看到,我可以用'ZipArchiveInputStream'替換ZipInputStream,但是我使用哪個流進行RAR/TAR。我應該一直保留'ArchiveInputStream'和'ArchiveEntry'嗎? – ha9u63ar

+0

如果您想使用Commons Compress處理所有格式,請使用常規Archive類。有關這樣做的一個好例子,請參閱[Apache Tika包解析器源代碼](https://git1-us-west.apache.org/repos/asf?p=tika.git;a=blob;f=tika -parsers/src/main/java/org/apache/tika/parser/pkg/CompressorParser.java; hb = HEAD) – Gagravarr