在多台主机上使用Java压缩文件压缩文件

时间:2013-05-26 14:55:49

标签: java parallel-processing zip distributed deflate

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

2 个答案:

答案 0 :(得分:4)

您需要使用nowrap的{​​{1}}选项生成没有标题或预告片的原始deflate流。然后,您需要自己用适当的zip标题和预告片包装原始的deflate流。

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

Java 7(但不是Java 6)zlib通过Z_SYNC_FLUSH方法的可选第四个参数支持此功能。可以将其设置为deflate()

以这种方式分解数据会降低压缩率,因为每个块都无法从前一个块的历史中受益。这可以使用SYNC_FLUSH方法解决。向每个线程提供要压缩的数据以及在其之前的32K字节的未压缩数据。然后使用带有setDictionary()的32K,然后使用setDictionary()

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

获得deflate流后,将其适当地换行以使其成为zip文件。请参阅pigz。您还需要计算未压缩数据的appnote for the zip file format才能填写这些字段。

答案 1 :(得分:0)

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

  1. 检查原始文件大小并确定大小的大小。
  2. 开始阅读文件,直到达到块大小。阅读时使用ZipOutputStream将内容写入zip。创建带有后缀的文件,以便稍后加入内容。后缀应该是运行索引。由于您要将一个文件存储在多个zip文件中,因此每个zip使用一个条目。
  3. 阅读zip文件时,只需根据后缀对其进行排序(请参阅前面的内容)并阅读您唯一的条目,然后将字节从ZipInputSteam复制到FileOutputStream
  4. 不幸的是,我不明白你的多个主机意味着什么。你的意思是你的文件太大了,你可以同时在单独的机器上创建每个拉链?如果这是正确的,请修改#2,如下所示:读取文件片段时,将其内容发送到远程主机并在那里使用ZipOutputStream。要从特定点读取文件,请使用InputStream.skip()