如何使用LWJGL的LZ4绑定压缩解压

How to use LWJGL's LZ4 bindings to compress and decompress

我正在尝试创建两种辅助方法,一种用于压缩,一种用于解压。这些方法应该使用 LWJGL 的 LZ4 绑定来完成 compression/decompression。

它们大部分已经可以工作了,但是解压后返回的字节数组有尾随零。

import static org.lwjgl.util.lz4.LZ4.LZ4_compressBound;
import static org.lwjgl.util.lz4.LZ4.LZ4_compress_default;
import static org.lwjgl.util.lz4.LZ4.LZ4_decompress_safe;

import java.nio.ByteBuffer;

public static byte[] compress(byte[] data) {
    ByteBuffer buffer = BufferUtils.createByteBuffer(data.length);
    for (int i = 0; i < data.length; i++) {
        buffer.put(data[i]);
    }
    buffer.flip();

    ByteBuffer destination = BufferUtils.createByteBuffer(LZ4_compressBound(buffer.remaining()));
    destination.clear();

    LZ4_compress_default(buffer, destination);

    return getByteArrayFromByteBuffer(destination);
}

public static byte[] decompress(byte[] data) {
    ByteBuffer buffer = BufferUtils.createByteBuffer(data.length);
    for (int i = 0; i < data.length; i++) {
        buffer.put(data[i]);
    }
    buffer.flip();

    ByteBuffer destination = BufferUtils.createByteBuffer(LZ4_compressBound(buffer.remaining()));
    destination.clear();

    LZ4_decompress_safe(buffer, destination);

    return getByteArrayFromByteBuffer(destination);
}

public static byte[] getByteArrayFromByteBuffer(ByteBuffer byteBuffer) {
    byte[] bytesArray = new byte[byteBuffer.remaining()];
    byteBuffer.get(bytesArray, 0, bytesArray.length);
    return bytesArray;
}

运行压缩后的结果(解压缩(SOME DATA)), 是:[SOME_DATA, 0, 0, 0].

数据的前半部分是正确的,但由于某些原因添加了额外的零。这可能是由于未正确设置 ByteBuffers,但我不确定。无论哪种方式,我怎样才能删除这些额外的零?

同样不幸的是,this 是我能找到的唯一一个 link 示例,展示了它应该如何工作。

首先,在压缩过程中,您当前使用的结果 LZ4_compressBound(...) to define the initial capacity of your destination buffer. While this is correct, you have to keep in mind that this is only the Worst-Case size of the compressed data. The actual amount of bytes written by LZ4_compress_default(...) 是所述函数的 return 值,可能小于界限。因此,您需要 trim 您的目标缓冲区以匹配该大小。

int compressedSize = LZ4_compress_default(buffer, destination);
destination.limit(compressedSize);
destination = destination.slice();

另外你的解压也有类似的bug: 您不能使用 LZ4_compressBound(...) 来计算目标缓冲区的容量。相反,您需要将解压缩数据的大小存储在别处。 (理论上你可以使用 compressedSize * 255 但这非常不切实际,因为压缩率几乎从未达到,因此会导致大量资源浪费。See here.) 同样,您需要遵守 LZ4_decompress_safe 的 return 值,这是解压缩数据的实际大小。