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 的最佳缓冲区大小是多少?

4

2 回答 2

10

简短的回答:我会选择像 16k 这样的东西。


长答案:

ZIP 使用 DEFLATE 算法进行压缩 ( http://en.wikipedia.org/wiki/DEFLATE )。Deflate 是 Ziv Lempel Welch 的一种风格(在维基百科中搜索 LZW)。DEFLATE 使用 LZ77 和 Huffman 编码。

这是一种字典压缩,据我所知,从算法的角度来看,将数据送入 deflater 时使用的缓冲区大小几乎没有影响。LZ77 的最大影响是字典大小和滑动窗口,在您的示例中不受缓冲区大小的控制。

我认为您可以根据需要尝试不同的缓冲区大小并绘制图表,但我相信您不会看到压缩比有任何显着变化(3/80000 = 0.00375%)。

由于调用 FileInputStream.read 和 zos.write 时执行的开销代码量,缓冲区大小对速度的影响最大。从这个角度来看,您应该考虑您获得的和花费的。

当从 1 字节增加到 1024 字节时,您会损失 1023 字节(理论上),并且在 .read 和 .write 方法中的开销时间减少了约 1024 倍。但是,当从 1k 增加到 64k 时,您将花费 63k,从而将开销减少了 64 倍。

所以这会带来收益递减,因此我会选择中间的某个地方(比如说 16k)并坚持下去。

于 2008-10-14T14:22:23.060 回答
0

取决于您拥有的硬件(磁盘速度和文件搜索时间)。我想说,如果您对压缩性能的最后一滴不感兴趣,请选择 4k 到 64k 之间的任何大小。由于它是一个短暂的对象,无论如何它都会很快被收集。

于 2008-10-14T13:08:45.893 回答