1

我的问题是 zip 压缩。我必须将文件分成几部分并并行压缩它们,然后以正确的顺序连接这些部分,并用一个文件保存为 zip 存档。拆分文件并将部分发送到主机不是问题 - 我使用的是 jpvm。我的问题是:如何拆分压缩?我尝试使用 java.util.zip.Deflater 压缩每个部分(结果是字节数组),然后将它们写入一个 ZipOutputStream,但这似乎不起作用 - 在保存到文件时它会压缩已经压缩的字节再一次。我是否必须使用 deflater 压缩每个部分,然后手动添加 zip 标头、一些校验和或类似的东西?Deflater 是否添加任何标题?感谢您的帮助,谢谢!

4

2 回答 2

4

您需要使用nowrap选项Deflater来生成没有标题或尾部的原始放气流。然后,您需要自己使用适当的 zip 标头和预告片来包装原始的 deflate 流。

要在多个处理器上创建单个 deflate 流,您需要能够使用zlibZ_SYNC_FLUSH中的操作将压缩输出刷新到字节边界(对于不是最后一个片段的片段) 。(最后一块将正常完成。)然后可以简单地连接这些块。

Java 7(但不是 Java 6)文档通过方法的可选第四个参数支持这一点deflate()。可以设置为SYNC_FLUSH.

以这种方式分解数据会降低压缩率,因为每个块都不能从前一个块的历史中受益。这可以使用该setDictionary()方法解决。向每个线程提供要压缩的数据以及它之前的 32K 字节未压缩数据。然后将 32K 与 一起使用setDictionary(),然后使用deflate().

您可以在pigz中看到直接使用 zlib 在 C 中进行并行压缩的示例。

一旦你有你的放气流,你适当地包装它以使其成为一个 zip 文件。有关 zip 文件格式,请参阅appnote。您还需要计算未压缩数据的CRC-32才能填写这些字段。

于 2013-05-26T18:09:24.967 回答
0

不幸的是,你没有显示你的代码,所以我不能确定我完全理解你的意思。但是,据我了解您的问题,我可以向您推荐以下内容。

  1. 检查原始文件大小并决定块的大小。
  2. 开始读取文件,直到达到块大小。在阅读时使用ZipOutputStream. 创建带有后缀的文件,以便您稍后加入内容。后缀应该是运行索引。由于您想将一个文件存储在多个 zip 文件中,因此每个 zip 使用一个条目。
  3. 读取 zip 文件时,只需根据后缀(见前面)对它们进行排序并读取您唯一的条目,然后将字节ZipInputSteamFileOutputStream.

不幸的是,我不明白您的多个主机是什么意思。你的意思是你的文件太大了,以至于你同时在不同的机器上创建了每个 zip?如果这是正确的修改#2如下:在读取文件片段时将其内容发送到远程主机并ZipOutputStream在那里使用。要从特定点读取文件,请使用InputStream.skip().

于 2013-05-26T15:07:47.897 回答