Estoy intentando crear dos métodos de ayuda, uno para comprimir y uno para descomprimir. Estos métodos deben usar los enlaces LZ4 de LWJGL para lograr la compresión / descompresión.

En su mayoría, trabajan, pero la matriz de bytes que se devuelve después de que la descompresión tiene ceros que arrastra.

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;
}

El resultado después de ejecutar compresa (descomprime (algunos datos)), es: [Some_Data, 0, 0, 0].

La primera mitad de los datos es correcta, pero por alguna razón se agregan ceros adicionales. Probablemente esto se debe a los bytebuffers que no se están configurando correctamente, pero no estoy seguro. De cualquier manera, ¿cómo puedo eliminar estos ceros adicionales?

También lamentablemente Este es el único enlace que pude encontrar, muestra un ejemplo de cómo se supone que esto funciona.

1
codedcosmos 1 jul. 2019 a las 10:52

1 respuesta

La mejor respuesta

En primer lugar, durante la compresión, actualmente está utilizando el resultado de LZ4_compressBound(...) para definir la capacidad inicial de su búfer de destino. Si bien esto es correcto, debe tener en cuenta que este es solo el peor de los casos de los datos comprimidos. La cantidad real de bytes escritos por LZ4_compress_default(...) es el valor de retorno de dicha función y probablemente menos que el límite. Por lo tanto, necesita recortar su búfer de destino para que coincida con ese tamaño.

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

Además, usted tiene un error similar en su descompresión: No puede usar LZ4_compressBound(...) para calcular la capacidad de su búfer de destino. En su lugar, necesita almacenar el tamaño de los datos descomprimidos en otros lugares. (En teoría, podría usar compressedSize * 255, pero esto es extremadamente imprecial ya que la relación de compresión casi nunca se logra y, por lo tanto, conduce a una gran cantidad de recursos desperdiciados. ver aquí. ) Y nuevamente necesitas respetar el valor de retorno de LZ4_decompress_safe que es el tamaño real de los datos descomprimidos.

1
TheMrMilchmann 1 jul. 2019 a las 17:52