高效的 LZ4 多文件压缩使用 Java

3
我使用了Adrien Grand的Java仓库,提供JNI到原始LZ4本地代码的转换。
我想压缩给定输入目录下的多个文件,但是LZ4不支持像Java zip包一样的多文件压缩,因此我尝试了另一种方法,即把所有输入文件打成tar包并将其作为输入流传递给LZ4压缩器,我使用了Jtar Java包来打tar包。除了这种方法,还有其他更好的方法吗? 我找到了许多样例代码来压缩字符串以及如何正确实现LZ4压缩器和解压缩器。现在我想知道如何实际应用于多个文件?我也想澄清我的方向是否正确。 在打完tar包后,根据样例代码使用说明,我需要先将tar包转换为字节数组,然后将其提供给压缩器模块。我使用apache-common-ioutil包来完成转换。考虑到我有很多输入文件,而且tar包很大,总是把它转换为字节数组似乎对我来说不太有效。我想先知道这是否有效?或者是否有更好的方法使用LZ4包比这更好? 我遇到的另一个问题是最终结果。在压缩tar文件之后,我将得到一个名为MyResult.lz4的输出文件,但是我无法使用存档管理器(我使用ubuntu)解压缩它,因为它不支持这种格式。我也不清楚此处要使用的档案和压缩格式。我还想知道最终结果应该是什么格式。所以现在我从用户角度来看待这个问题,考虑一下如果我为用户生成备份,如果我为他/她提供传统的.zip、.gz或任何已知格式,用户将能够自己解压缩它。我知道LZ4并不意味着我必须期望用户也应该了解这种格式,对吗?他甚至可能在看到这种格式时感到困惑。这意味着从.lz4转换到.zip格式似乎也毫无意义。我已经看到打tar包所有输入文件的过程非常耗时,所以我想知道它会影响多少性能。我已经在Java zip包中看到压缩多个输入文件似乎根本不是问题。所以在LZ4之后,我遇到了Apache common compress和TrueZIP。我还找到了一些关于它们的stackoverflow链接,这些链接帮助我学了很多。目前我真的想使用LZ4进行压缩,尤其是由于它的性能,但我遇到了这些障碍。有没有对LZ4包有很好了解的人提供我的所有问题和问题的解决方案以及简单的实现方法呢?谢谢。
我计算出一个由多个文件组成的输入所需的时间,
打tar包需要的时间:4704毫秒
把文件转换为字节数组需要的时间:7毫秒
压缩需要的时间:33毫秒
3个回答

3

一些事实:

  1. LZ4在这里与GZIP没有区别:它是一个单一问题的项目,处理压缩。它不涉及档案结构。这是故意的。
  2. Adrien Grand的LZ4库生成的输出与命令行LZ4实用程序不兼容。这也是故意的。
  3. 你使用tar的方法似乎没问题,因为这就是使用GZIP的方法。

理想情况下,您应该使tar代码产生立即被压缩的流,而不是先完全存储在RAM中。这就是使用Unix管道在命令行上实现的效果。


1

我有同样的问题。目前Java的LZ4版本与后来开发的处理流的LZ4标准不兼容, 但是在项目仓库中,有一个支持标准压缩/解压流的补丁,并且我可以确认它兼容命令行工具。你可以在这里找到它https://github.com/jpountz/lz4-java/pull/61

在Java中,您可以将它与Apache Commons压缩的TarArchiveInputStream一起使用。

如果您需要示例,我使用的代码位于Maven构件io.github.htools 0.27-SNAPSHOT中(或者在GitHub上),类io.github.htools.io.compressed.TarLz4FileWriter和(过时的类)io.github.htools.io.compressed.TarLz4File展示了如何工作。在HTools中,当您的文件名以.tar.lz4结尾时,tar和lz4会自动通过ArchiveFile.getReader(String filename) 和 ArchiveFileWriter(String filename, int compressionlevel) 使用。


0

您可以将IOStreams链接在一起,因此可以使用来自Apache Commons的Tar Archive和来自lz4-java的LZ4之类的东西。

try (LZ4FrameOutputStream outputStream = new LZ4FrameOutputStream(new FileOutputStream("path/to/myfile.tar.lz4"));
     TarArchiveOutputStream taos = new TarArchiveOutputStream (outputStream))  {

   ...

}

将字节合并成字节数组会导致瓶颈,因为您不尝试将整个流保存在内存中,这可能会在处理大型流时轻易遇到OutOfMemory问题。 相反,您需要像上面一样将字节通过所有IOStreams进行管道传输。

我创建了一个Java库来为您完成此操作https://github.com/spoorn/tar-lz4-java

如果您想要自己实现它,这里有一个技术文档,其中包括使用Apache Commons的TarArchive和lz4-java压缩目录的详细信息: https://github.com/spoorn/tar-lz4-java/blob/main/SUMMARY.md#lz4


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接