2013-12-16 60 views
2

我的應用程序需要一個雙字節列表,編碼爲一個字節數組,其小數位編碼已被zlib壓縮,然後編碼爲基礎64.我寫了一個線束來測試我的編碼,這是行不通的。我能夠取得進展。Java壓縮字節數組和基礎64編碼到基礎64解碼和解壓縮字節數組錯誤:不同大小的輸入/輸出數組

但是,我注意到,當我嘗試解壓縮到一個固定大小的緩衝區時,我能夠拿出輸入,使解壓縮的字節數組的大小比原始字節數組小,這顯然不是對。與此同時,列表中的最後一個雙重消失。在大多數輸入上,固定緩衝區大小再現輸入。有誰知道爲什麼會這樣?我猜測錯誤是以我編碼數據的方式進行的,但我無法弄清楚發生了什麼問題。

當我嘗試使用ByteArrayOutputStream處理任意大小的可變長度輸出(這對於實際版本的代碼很重要,因爲我無法保證最大大小限制),Inflater的膨脹方法不斷返回我查閱了文檔,它說這意味着它需要更多的數據。由於沒有更多的數據,我再次懷疑我的編碼,並猜測這是導致先前解釋的行爲的相同問題。

在我的代碼中,我已經包含了一個數據工作正常的固定緩衝區大小的例子,以及不適用於固定緩衝區的數據。這兩個數據集都會導致我解釋的可變緩衝區大小錯誤。

任何線索,我做錯了什麼?非常感謝。

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

}

+0

我知道這聽起來很奇怪,但你不能假定壓縮的數據不會比未壓縮的數據大。 – BevynQ

+0

嘗試'byte [] output = new byte [input.length * 2];'in compressControids – BevynQ

回答

1

當壓縮數據我們真正做的是re-encoding增加熵的數據。在reecoding過程中,我們必須添加元數據來告訴我們如何編碼數據,以便將其轉換回以前的數據。

如果只有meta data size is less比我們節省的空間reencoding the data壓縮將只會成功。

考慮Huffman encoding

霍夫曼是我們與variable width character set加上字符集長度表更換fixed width character set一個簡單的編碼方案。出於顯而易見的原因,長度表大小將大於0。如果所有字符的分佈幾乎相等,我們將無法保存任何空間。所以我們的壓縮數據最終比我們的未壓縮數據大。

+0

非常感謝BevynQ。我永遠不會猜測壓縮的數據會比未壓縮的數據大。再次感謝! 對於任何絆倒這個的人來說,解決方案是在compressCentroids中使byte [] output = new byte [input.length * 2] – user1385440