我的问题是 zip 压缩。我必须将文件分成几部分并并行压缩它们,然后以正确的顺序连接各部分并使用一个文件另存为 zip 存档。分割文件并将部分发送到主机不是问题 - 我正在使用 jpvm。我的问题是:如何分割压缩?我尝试使用 java.util.zip.Deflater 来压缩每个部分(结果是字节数组),然后将它们写入一个 ZipOutputStream,但这似乎不起作用 - 在保存到文件时它会压缩已经压缩的字节再一次。我是否必须使用 deflater 压缩每个部分,然后手动添加 zip 标头、一些校验和或类似的内容? Deflater 是否添加任何标头?感谢您的帮助,谢谢!
您需要使用
nowrap
的 Deflater
选项来生成没有标头或标尾的原始 deflate 流。 然后,您需要自己使用适当的 zip 标头和预告片包装原始 deflate 流。
要在多个处理器上创建单个 deflate 流,您需要能够使用
zlib中的
Z_SYNC_FLUSH
操作将压缩输出刷新到字节边界(对于不是最后一块的部分)。 (最后一块会正常完成。)然后可以简单地将这些块连接起来。
Java 7(但不是 Java 6)文档 通过
deflate()
方法的可选第四个参数支持此操作。 可以设置为 SYNC_FLUSH
。
以这种方式分解数据会降低压缩性能,因为每个块都无法从前一个块的历史记录中受益。 这可以使用
setDictionary()
方法来解决。 向每个线程提供要压缩的数据以及其前面的 32K 字节的未压缩数据。 然后使用 32K 和 setDictionary()
,然后是 deflate()
。
您可以查看pigz,了解直接使用 zlib 在 C 语言中并行压缩的示例。
获得 deflate 流后,将其适当包装以使其成为 zip 文件。 请参阅应用说明了解 zip 文件格式。 您还需要计算未压缩数据的 CRC-32 才能填充这些字段。
不幸的是,您没有显示您的代码,所以我不能确定我是否完全理解您的意思。但是,据我了解您的问题,我可以向您推荐以下内容。
ZipOutputStream
将内容写入 zip 中。创建带有后缀的文件,以便您稍后加入内容。后缀应该是运行索引。由于您想要将一个文件存储在多个 zip 文件中,因此每个 zip 使用一个条目。 ZipInputSteam
复制到您的 FileOutputStream
。 不幸的是我不明白你的多个主机到底是什么意思。您的意思是您的文件太大,以至于您同时在不同的计算机上创建每个 zip 吗?如果这是正确的,则修改 #2 如下:在读取文件片段时,将其内容发送到远程主机并在那里使用
ZipOutputStream
。要从特定点读取文件,请使用 InputStream.skip()
。
以下是如何将并行压缩条目写入 JVM 上的单个 zip 文件: