2011-01-11 44 views
5

我有一些關於java.util.zip庫的一般問題。 我們基本上做的是導入和導出許多小組件。以前這些成分是進口和使用單個大文件,例如:java.util.zip - ZipInputStream v.s. ZipFile

<component-type-a id="1"/> 
<component-type-a id="2"/> 
<component-type-a id="N"/> 

<component-type-b id="1"/> 
<component-type-b id="2"/> 
<component-type-b id="N"/> 

請注意,組件的進口過程中的順序是相關的出口。

現在每個組件應該佔據自己的文件應該是外部版本,QA-ED,BLA BLA。我們決定輸出的輸出應該是一個zip文件(包含所有這些文件),我們輸入的輸入應該是一個類似的zip文件。我們不想在我們的系統中爆炸拉鍊。我們不希望爲每個小文件打開單獨的流。我目前的問題:

Q1。可能ZipInputStream保證壓縮條目(小文件)的讀取順序與我們使用ZipOutputStream的導出時插入的順序相同?我認爲閱讀是一樣的東西:


ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis)); 
ZipEntry entry; 
while((entry = zis.getNextEntry()) != null) 
{ 
     //read from zis until available 
} 

我知道,中央拉鍊目錄將被置於在zip文件的末尾但儘管如此裏面的文件條目具有順序。我也知道依靠這個命令是一個醜陋的想法,但我只想記住所有的事實。 Q2302。如果我使用ZipFile(我更喜歡),那麼調用getInputStream()幾百次會帶來怎樣的性能影響?它會比ZipInputStream解決方案慢嗎?該郵編只打開一次,ZipFile支持RandomAccessFile - 這是正確的嗎? 我假設讀數是這樣的:


ZipFile zipfile = new ZipFile(argv[0]); 
Enumeration e = zipfile.entries();//TODO: assure the order of the entries 
while(e.hasMoreElements()) { 
     entry = (ZipEntry) e.nextElement(); 
     is = zipfile.getInputStream(entry)); 
} 

Q3。是否從相同的ZipFile線程安全地檢索輸入流(例如,我可以同時在不同線程中讀取不同的條目)?任何表現處罰?

感謝您的回答!

回答

3

問題1:是的,訂單將與添加條目相同。 Q2:請注意,由於zip檔案文件的結構和壓縮,沒有任何解決方案是完全流式傳輸的;他們都做了一定程度的緩衝。如果您簽出JDK源代碼,實現將共享大部分代碼。儘管索引允許查找與條目相對應的塊,但內容中沒有真正的隨機訪問。所以我認爲不應該有意義的性能差異;特別是操作系統無論如何都會緩存磁盤塊。您可能只想測試性能以通過簡單的測試用例來驗證。

Q3:我不會指望這一點;很可能他們不是。如果你真的認爲併發訪問會有幫助(主要是因爲解壓縮是CPU綁定的,所以它可能會有所幫助),我會嘗試讀取內存中的整個文件,通過ByteArrayInputStream公開,並構建多個獨立的讀取器。

+0

嗨StaxMan!我只是在JDK6中檢查ZipFile $ ZipFileInputStream的實現。這是由ZipFile.getInputStream返回它有同步,但我真的不知道這是多麼可靠。 – 2011-01-11 18:05:14

+0

是的,我不能肯定地說它是非線程安全的。另一個更危險的部分是底層本地zlib庫,我懷疑它不是線程安全的。 – StaxMan 2011-01-11 18:07:35

0

關於Q3,在JENKINS-14362經驗表明,zlib的是不是線程安全甚至無關的流,即操作時,它有一些不正確的共享靜止狀態。沒有證明,只是一個警告。

1

我測量到,只列出ZipInputStream的文件比使用ZipFile慢8倍。

long t = System.nanoTime(); 
    ZipFile zip = new ZipFile(jarFile); 
    Enumeration<? extends ZipEntry> entries = zip.entries(); 
    while (entries.hasMoreElements()) 
    { 
     ZipEntry entry = entries.nextElement(); 

     String filename = entry.getName(); 
     if (!filename.startsWith(JAR_TEXTURE_PATH)) 
      continue; 

     textureFiles.add(filename); 
    } 
    zip.close(); 
    System.out.println((System.nanoTime() - t)/1e9); 

long t = System.nanoTime(); 
    ZipInputStream zip = new ZipInputStream(new FileInputStream(jarFile)); 
    ZipEntry entry; 
    while ((entry = zip.getNextEntry()) != null) 
    { 
     String filename = entry.getName(); 
     if (!filename.startsWith(JAR_TEXTURE_PATH)) 
      continue; 

     textureFiles.add(filename); 
    } 
    zip.close(); 
    System.out.println((System.nanoTime() - t)/1e9); 

(不要在同一類運行它們。讓兩個不同的類,並分別運行它們)