使用Java创建.zip压缩文件时的缓冲区大小是多少?

7
我使用这段代码创建一个包含文件列表的.zip文件:
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile));

for (int i=0;i<srcFiles.length;i++){
    String fileName=srcFiles[i].getName();
    ZipEntry zipEntry = new ZipEntry(fileName);
    zos.putNextEntry(zipEntry);
    InputStream fis = new FileInputStream(srcFiles[i]);
    int read;
    for(byte[] buffer=new byte[1024];(read=fis.read(buffer))>0;){
        zos.write(buffer,0,read);
    }
    fis.close();
    zos.closeEntry();
}
zos.close();

我不知道zip算法和ZipOutputStream是如何工作的,如果在读取并将所有数据发送到“zos”之前它写入了一些内容,那么结果文件的大小可能会与选择另一个缓冲区大小时不同。
换句话说,我不知道算法是否是这样的:
读取数据-->处理数据-->创建 .ZIP
还是:
读取数据块-->处理数据块-->将数据块写入 .ZIP-->| ^---------------------------------------------------|
如果是这种情况,最佳的缓冲区大小是多少?
更新:
我已经测试了这段代码,将缓冲区大小从1024更改为64,并压缩相同的文件:使用1024字节时,80 KB的结果文件比使用64字节缓冲区小3个字节。哪种缓冲区大小可以在最短时间内生成最小的 .zip 文件?
2个回答

10

简短回答:我会选择类似16k的大小。


长回答:

ZIP使用DEFLATE算法进行压缩(http://en.wikipedia.org/wiki/DEFLATE)。Deflate是Ziv Lempel Welch的一种变体(搜索维基百科以获取有关LZW的信息)。DEFLATE使用了LZ77和Huffman编码。

这是一种字典压缩,就算从算法角度看,在将数据输入到压缩程序中时使用的缓冲区大小几乎没有影响。LZ77受到的最大影响是字典大小和滑动窗口,这些因素都不受你示例中的缓冲区大小控制。

如果你想要尝试不同的缓冲区大小并绘制图像,我认为你不会看到任何明显的压缩比率变化(3/80000 = 0.00375%)。

缓冲区大小对速度的影响最大,原因是每次调用FileInputStream.read和zos.write时执行了很多额外的代码。所以你应该考虑你获得了什么和你花费了什么。

当从1字节增加到1024字节时,你会损失1023字节(理论上),并获得一个约为1024的减少在.read和.write方法中的开销时间。 然而,当从1k增加到64k时,你会花费63k,将开销降低了64倍。

因此这是递减收益,所以我会选择中间值(比如16k)并坚持使用它。


我接受这个答案,因为它表明缓冲区大小并不显著影响结果大小,而是字典大小和滑动窗口。 - Telcontar

0

这取决于您拥有的硬件(磁盘速度和文件搜索时间)。如果您不想挤出最后一滴性能,我建议选择4k到64k之间的任何大小。由于它是一个短暂的对象,它会很快被收集。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接