在多个主机上使用Java中的zip算法压缩文件

问题描述 投票:0回答:3

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

java parallel-processing zip distributed deflate
3个回答
4
投票

您需要使用

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 才能填充这些字段。


0
投票

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

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

不幸的是我不明白你的多个主机到底是什么意思。您的意思是您的文件太大,以至于您同时在不同的计算机上创建每个 zip 吗?如果这是正确的,则修改 #2 如下:在读取文件片段时,将其内容发送到远程主机并在那里使用

ZipOutputStream
。要从特定点读取文件,请使用
InputStream.skip()


0
投票

以下是如何将并行压缩条目写入 JVM 上的单个 zip 文件:

https://github.com/gregsh/parallel-zip

© www.soinside.com 2019 - 2024. All rights reserved.