如何在Java中正确地实现LZ4、Snappy或等效的压缩技术?

3
我曾尝试将Java版LZ4应用于搜索引擎程序,以搜索大型文本文件中的数据。我只是压缩了输出流并将其存储到没有名称的txt文件或文件中。然而,我发现所谓的压缩文件并没有减小大小,反而比原始文件更大。
最后我不得不使用zip4j,因为它对我有效。
我想知道如何正确地使用LZ4或Snappy的jar文件进行压缩/解压缩?
此外,我如何使用这些算法来压缩一个包含许多文件的单个文件夹?
谢谢!

你尝试过什么没有成功吗?从概念上讲,您只需使用提供压缩的OutputStream将FileOutputStream包装,然后写入该流。如果您正在编写文本,则可能需要使用OutputStreamWriter或PrintWriter进行包装。https://oss.sonatype.org/service/local/repositories/releases/archive/org/xerial/snappy/snappy-java/1.1.0/snappy-java-1.1.0-javadoc.jar/!/org/xerial/snappy/SnappyFramedOutputStream.html - Brett Okken
2个回答

5
我曾经遇到过相似的问题。我试图将一个大文件(约709 MB)分块以每个8192字节的速度通过本地网络发送。为了减少网络带宽,我使用了Lz4压缩/解压缩技术。

因此,如果你正在尝试做类似的事情,这是我的建议:

下面是在https://github.com/jpountz/lz4-java找到的类似常规示例的代码片段。

private static int decompressedLength;
private static LZ4Factory factory = LZ4Factory.fastestInstance();
private static LZ4Compressor compressor = factory.fastCompressor();

public static byte[] compress(byte[] src, int srcLen) {
    decompressedLength = srcLen;
    int maxCompressedLength = compressor.maxCompressedLength(decompressedLength);
    byte[] compressed = new byte[maxCompressedLength];
    compressor.compress(src, 0, decompressedLength, compressed, 0, maxCompressedLength);
    return compressed;
}

现在,如果你直接返回压缩后的字节数组,那么它的长度很有可能比原始的未压缩数据还要长。

因此,你可以按照以下方式进行修改:

private static int decompressedLength;
private static LZ4Factory factory = LZ4Factory.fastestInstance();
private static LZ4Compressor compressor = factory.fastCompressor();

public static byte[] compress(byte[] src, int srcLen) {
    decompressedLength = srcLen;
    int maxCompressedLength = compressor.maxCompressedLength(decompressedLength);
    byte[] compressed = new byte[maxCompressedLength];
    int compressLen = compressor.compress(src, 0, decompressedLength, compressed, 0, maxCompressedLength);
    byte[] finalCompressedArray = Arrays.copyOf(compressed, compressLen);
    return finalCompressedArray;
}

compressLen 存储了实际压缩的长度,finalCompressedArray 字节数组(长度为 compressLen)存储了实际压缩后的数据。一般来说,它的长度比compressed 字节数组和原始的 uncompressed 字节数组都要小。

现在,您可以按照以下常规方式对 finalCompressedArray 字节数组进行解压缩:

private static LZ4FastDecompressor decompressor = factory.fastDecompressor();

public static byte[] decompress(byte[] finalCompressedArray, int decompressedLength) {
    byte[] restored = new byte[decompressedLength];
    restored = decompressor.decompress(finalCompressedArray, decompressedLength);
    return restored;
}

非常抱歉回复这么晚! - kdenz
2
@Ankit- 如果我不知道解压缩后的字节数组大小,那么解压缩长度将是多少? - ketan
你必须将它存储在某个地方或进行传输。Lz4有示例代码,称为OutputStreamWithLength,其中它首先存储4个字节的未压缩大小。 - razor

1

.jar 文件是一个 .zip 文件。Zip文件格式不支持LZ4或Snappy。


1
抱歉,弄错了问题!:P 我的意思是如何使用LZ4或Snappy来压缩大型文本文件? - kdenz

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