Java压缩字节数组和base 64编码到base 64解码和解压缩字节数组错误:不同大小的输入/输出数组

时间:2013-12-16 23:09:39

标签: java zlib compression

我的应用程序需要一个编码为字节数组的双精度列表,其中的小端编码已被zlib压缩,然后编码为基数64.我编写了一个线束来测试我的编码,但这并不起作用。我能够取得进步。

然而,我注意到当我尝试解压缩到固定大小的缓冲区时,我能够得到输入,使得解压缩的字节数组的大小小于原始字节数组,这显然不是“#”。对。与此同时,列表中的最后一个双重消失。在大多数输入上,固定缓冲区大小再现输入。有谁知道为什么会这样?我猜测错误是我编码数据的方式,但我无法弄清楚出了什么问题。

当我尝试使用ByteArrayOutputStream处理任意大小的可变长度输出时(这对于代码的真实版本很重要,因为我不能保证最大大小限制),Inflater的膨胀方法不断返回0.我查阅了文档,它说这意味着它需要更多数据。由于没有更多的数据,我再次怀疑我的编码,并猜测它是导致先前解释的行为的相同问题。

在我的代码中,我提供了一个数据示例,该数据在固定缓冲区大小下运行良好,以及对固定缓冲区不起作用的数据。这两个数据集都会导致我解释的变量缓冲区大小错误。

关于我做错了什么的线索?非常感谢。

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
import org.apache.commons.codec.binary.Base64;

public class BinaryReaderWriter {
    public static void main(String [ ] args) throws UnsupportedEncodingException, DataFormatException
{
    // this input will break the fixed buffer method
    //double[] centroids = {123.1212234143345453223123123, 28464632322456781.23, 3123121.0};

    // this input will break the fixed buffer method
    double[] centroids = {123.1212234143345453223123123, 28464632322456781.23, 31.0};
    BinaryReaderWriter brw = new BinaryReaderWriter();
    String output = brw.compressCentroids(centroids);
    brw.decompressCentroids(output);
}
void decompressCentroids(String encoded) throws DataFormatException{
    byte[] binArray = Base64.decodeBase64(encoded);


    // This block of code is the fixed buffer version
    //
System.out.println("binArray length " + binArray.length);
    Inflater deCompressor = new Inflater();
    deCompressor.setInput(binArray, 0, binArray.length);
    byte[] decompressed = new byte[1024];
    int decompressedLength = deCompressor.inflate(decompressed);
    deCompressor.end();
System.out.println("decompressedLength = " + decompressedLength);
    byte[] decompressedData = new byte[decompressedLength];
    for(int i=0;i<decompressedLength;i++){
        decompressedData[i] = decompressed[i];
    }


    /*
    // This block of code is the variable buffer version
    //
    ByteArrayOutputStream bos = new ByteArrayOutputStream(binArray.length);
    Inflater deCompressor = new Inflater();
    deCompressor.setInput(binArray, 0, binArray.length);
    byte[] decompressed = new byte[1024];
    while (!deCompressor.finished()) {
        int decompressedLength = deCompressor.inflate(decompressed);
        bos.write(decompressed, 0, decompressedLength);
    }
    deCompressor.end();
    byte[] decompressedData = bos.toByteArray();
    */

    ByteBuffer bb = ByteBuffer.wrap(decompressedData);
    bb.order(ByteOrder.LITTLE_ENDIAN);
System.out.println("decompressedData length = " + decompressedData.length);
    double[] doubleValues = new double[decompressedData.length / 8];
    for (int i = 0; i< doubleValues.length; i++){
        doubleValues[i] = bb.getDouble(i * 8);
    }

    for(double dbl : doubleValues){
        System.out.println(dbl);
    }   
}

String compressCentroids(double[] centroids){
    byte[] cinput = new byte[centroids.length * 8];
    ByteBuffer buf = ByteBuffer.wrap(cinput);
    buf.order(ByteOrder.LITTLE_ENDIAN);
    for (double cent : centroids){
        buf.putDouble(cent);
    }

    byte[] input = buf.array();
System.out.println("raw length = " + input.length);
    byte[] output = new byte[input.length];
    Deflater compresser = new Deflater();
    compresser.setInput(input);
    compresser.finish();
    int compressedLength = compresser.deflate(output);
    compresser.end();
System.out.println("Compressed length = " + compressedLength);
    byte[] compressed = new byte[compressedLength];
    for(int i = 0; i < compressedLength; i++){
        compressed[i] = output[i];
    }

    String decrypted = Base64.encodeBase64String(compressed);
    return decrypted;
}

}

1 个答案:

答案 0 :(得分:1)

压缩数据时我们真正做的是re-encoding来增加数据中的熵。在重新编码过程中,我们必须添加元数据来告诉我们如何对数据进行编码,以便将其转换回以前的数据。

只有meta data size is less比我们reencoding the data节省的空间,压缩才会成功。

考虑Huffman encoding

Huffman是一种简单的编码方案,我们用fixed width character set和charset长度表替换variable width character set。由于显而易见的原因,长度表大小将大于0。如果所有字符的分布几乎相等,我们将无法保存任何空间。因此,我们的压缩数据最终会比我们的未压缩数据更大。