2009-11-20 133 views
8

我需要通過Java類ZipOutputStream壓縮一個Big文件(〜450 Mbyte)。這個大的維度導致了我的JVM堆空間的「OutOfMemory」錯誤。發生這種情況是因爲「zos.write(...)」方法在壓縮之前將所有文件內容存儲在內部字節數組中。使用Java壓縮ZIP文件中的大文件

  origin = new BufferedInputStream(fi, BUFFER); 
     ZipEntry entry = new ZipEntry(filePath); 
     zos.putNextEntry(entry); 

     int count; 
     while ((count = origin.read(data, 0, BUFFER)) != -1) 
     { 
      zos.write(data, 0, count); 
     } 
     origin.close(); 

自然的解決方法是將放大JVM的堆內存空間,但我想知道是否有寫以流的方式這個數據的方法。我不需要高壓縮率,所以我也可以改變算法。

沒有人有想法嗎?

+1

BUFFER有多大? – 2009-11-20 14:34:31

+0

正如我寫的2048 – robob 2009-11-20 14:55:59

回答

8

根據您對Sam的回覆的評論,您明顯創建了一個ZipOutputStream,它包裝了一個ByteArrayOutputStream。 ByteArrayOutputStream當然會將壓縮結果緩存在內存中。如果您希望將其寫入磁盤,則必須將ZipOutputStream包裝到FileOutputStream中。

+0

好吧,我明白你告訴我,但壓縮的數據是大約60 MByte ......低到運行「OutOfSpace」堆錯誤。那它呢?我必須將Xmx1024m設置爲好! 可能是我的錯! – robob 2009-11-20 15:09:05

+2

+1,使用FileOutputStream將zip寫入磁盤,或者如果您想直接將其傳輸到瀏覽器,請使用HttpServletResponse outputStream。 – 2009-11-20 17:24:54

+1

當你使用默認的JVM設置時,60M字節內存爆炸了嗎?如果是這樣,那聽起來是正確的。即使你的JVM在某個時候以64M的堆大小運行,ByteArrayOutputStream將需要擴展那個byte []數組......這意味着一個完整的副本。 – PSpeed 2009-11-20 21:34:40

3

有一個名爲TrueZip的圖書館,我曾經用它來取得很好的成績,以做這種事情。

我不能保證它在緩衝前端更好。我知道它使用自己的編碼做了很多事情,而不是依賴於JDK的Zip API。

所以這是值得一試,在我看來。

1

ZipOutputStream是基於流的,它不支持內存。你的BUFFER可能太大了。

+0

我的緩衝區是2048字節,我不認爲它太大! 這是例外: 異常在線程 「主」 java.lang.OutOfMemoryError:Java堆空間 \t在java.util.Arrays.copyOf(Arrays.java:2786) \t在java.io.ByteArrayOutputStream中。寫(ByteArrayOutputStream.java:94) \t在java.util.zip.DeflaterOutputStream.deflate(DeflaterOutputStream.java:161) \t在java.util.zip.DeflaterOutputStream.write(DeflaterOutputStream.java:118) \t在java的.util.zip.ZipOutputStream.write(ZipOutputStream.java:272) – robob 2009-11-20 14:54:59

0

我不知道是否因爲你將內容存儲在一個ZipEntry中,也許它在寫出ZipEntry之前基本上加載了它的所有內容。你必須使用Zip嗎?如果只需要壓縮一個數據流,則可以查看GZIPOutputStream。我相信它不會有同樣的問題。

希望這會有所幫助。

+0

我需要在Zip文件中存儲一個目錄內容以通過Web服務發送 – robob 2009-11-20 14:57:59

+2

聲音l如果你的回覆中有這麼大的對象,就不好意思。考慮返回一個URL,而不是從可以檢索zip文件的地方返回。平原小服務程序允許基於字節的流式響應。 – 2009-11-20 17:23:53

+0

你是對的我認爲這是正確的選擇。 – robob 2009-11-23 13:12:25