2009-11-20 128 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