繁体   English   中英

使用java进行高效的LZ4多文件压缩

[英]Efficient LZ4 multiple file compression using java

我采用了 adrien grand 的 java 存储库,为原始 LZ4 本机代码提供了 JNI。

我想在给定的输入目录下压缩多个文件,但是 LZ4 不支持像 java zip 包中那样的多个文件压缩,所以我尝试了另一种方法,我想将所有输入文件 tar 并将其作为输入传递给 LZ4 压缩器,我使用 Jtar java 包对所有输入文件进行去皮重处理。 除了这个还有其他更好的方法吗?

我遇到了许多示例代码来压缩一些字符串以及如何正确实现 LZ4 压缩器和解压缩器。 现在我想知道如何为多个文件实际实现它? 我还想澄清我是否朝着正确的方向前进。

在对所有文件进行去皮重后,根据示例代码使用说明,我现在必须将去皮重文件转换为字节数组以将其提供给压缩器模块。 为此,我使用了 apache-common-ioutil 包。 因此,考虑到我有很多文件作为输入,这会导致 tar 的大小非常大,因此在我看来,总是将其转换为字节数组似乎是无效的。 我想先知道这是否有效? 或者有没有比这更好地使用 LZ4 包的更好方法?

我遇到的另一个问题是最终结果。 压缩去皮重的文件后,我会得到像 MyResult.lz4 文件这样的最终结果作为输出,但我无法使用存档管理器(我正在使用 ubuntu )解压缩它,因为它不支持这种格式。 我也不清楚我必须在这里使用的存档和压缩格式。 我也想知道最终结果应该是什么格式。所以现在我从用户的角度说,考虑一个我为用户生成备份的情况,如果我向他/她提供传统的 .zip , .gz 或任何已知格式,用户可以自行解压缩。 据我所知,LZ4 并不意味着我期望用户也应该知道这种格式,对吧? 看到这样的格式,他甚至可能会感到困惑。 所以这意味着从 .lz4 到 .zip 格式的转换似乎也毫无意义。 我已经将所有输入文件的去皮重过程视为一个耗时的过程,因此我想知道它对性能的影响有多大。 正如我在 java zip 包中看到的那样,压缩多个输入文件似乎根本不是问题。 所以在 lz4 旁边,我遇到了 Apache common compress 和 TrueZIP。 我还遇到了几个关于它们的堆栈溢出链接,这帮助我学到了很多东西。 到目前为止,我真的很想使用 LZ4 进行压缩,尤其是因为它的性能,但我遇到了这些障碍。 任何对 LZ4 包有很好了解的人都可以为我的所有查询和问题提供解决方案以及简单的实现。 谢谢。

我为包含许多文件的输入计算的时间,
去皮时间 : 4704 ms
将文件转换为字节数组所需的时间:7 毫秒
压缩时间:33 ms

一些事实:

  1. LZ4 在这里与 GZIP 没有什么不同:它是一个单一关注项目,处理压缩。 它不处理归档结构。 这是故意的。
  2. Adrien Grand 的 LZ4 库产生的输出与命令行 LZ4 实用程序不兼容。 这也是故意的。
  3. 您使用 tar 的方法似乎没问题,因为这就是使用 GZIP 的方式。

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

我有同样的问题。 当前版本的 LZ4 for Java 与后来开发的处理流的 LZ4 标准不兼容,但是,在项目 repo 中有一个补丁支持该标准来压缩/解压缩流,我可以确认它与命令行兼容工具。 你可以在这里找到它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 结尾,则通过 ArchiveFile.getReader(String filename) 和 ArchiveFileWriter(String filename, int compressionlevel) 自动使用 tar 和 lz4

您可以将 IOStream 链接在一起,因此使用 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 的 LZ4 压缩目录的详细信息:https ://github.com/spoorn/tar-lz4-java/blob/主/SUMMARY.md#lz4

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM