如何使用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 值,这是解压缩数据的实际大小。
我正在尝试创建两种辅助方法,一种用于压缩,一种用于解压。这些方法应该使用 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 值,这是解压缩数据的实际大小。