2011-10-18 64 views
0

我已經實現了使用優先級隊列的Java中的Huffman編碼算法,其中我遍歷了樹從根到葉,並根據符號出現的次數獲取編碼示例爲#= 000011在輸入中。一切都很好,樹木製作得很好,編碼和預期一樣:但是我得到的輸出文件比原始文件大。我正在遍歷樹的左節點和右節點,將'0'&'1'附加到字符串。也許我最終會使用每個字符的全部8位,並且它對壓縮沒有幫助。我猜測這些位有一些轉換成字符值是必需的。所以這些字符使用的位數少於8,因此我得到了原始文件的壓縮版本。您可以讓我知道如何通過操縱字符和減少Java中的位來實現壓縮?謝謝無法在Java中的Huffman編碼期間壓縮文件

回答

0

您可能正在使用StringBuilder並附加「0」或「1」,或者簡單地使用+運算符將「0」或「1」連接到字符串的末尾。或者你正在使用某種OutputStream並寫入它。

你想要做的就是寫出實際的位。我建議在寫之前先寫一個完整的字節。一個字節看起來像這樣:

0x05 

這將代表二進制字符串0000 0011

可以通過使byte型,添加和移動使這些:

public void writeToFile(String binaryString, OutputStream os){ 
    int pos = 0; 
    while(pos < binaryString.length()){ 
     byte nextByte = 0x00; 
     for(int i=0;i<8 && pos+i < binaryString.length(); i++){ 
      nextByte << 1; 
      nextByte += binaryString.charAt(pos+i)=='0'?0x0:0x1; 
     } 
     os.write(nextByte); 
     pos+=8; 
    } 
} 

當然,這是低效率的,在一個時間來寫一個字節,並且最重要的是所述的OutputStream接口只接受字節數組(byte[])。所以你最好將字節存儲在一個數組中(或者更簡單,一個List),然後將它們寫入更大的塊。

如果你不允許使用字節寫入(爲什麼heck不是?ObjectOutputStream支持寫入字節數組!),那麼你可以使用Base64來編碼你的二進制字符串。但請記住,Base64使您的數據使用率增加了33%。

將字節數組轉換爲base64的簡單方法是使用現有的編碼器。

import sun.misc.BASE64Encoder; 

您可以實例化編碼器,把您的字節數組轉換爲字符串:添加以下導入後

byte[] bytes = getBytesFromHuffmanEncoding(); 
BASE64Encoder encoder = new BASE64Encoder(); 
String encodedString = encoder.encode(bytes); 
+0

你說得對,我使用的是+運算符來連接「0」或' 1'到字符串的末尾。但是我需要使用字符串「Str」將輸出寫入Ascii 32位格式的文件(而不是寫入實際位),正如您所建議的那樣。我可以做到這一點嗎?代碼是ObjectOutputStream ObjOutputStream = new ObjectOutputStream(new FileOutputStream(EncFile)); \t \t ObjOutputStream.writeObject(Str); – PC2015

+0

也許我可以將每個獲得的字節轉換爲字符並將其存儲在String Str中? – PC2015

+0

@ user997509這幾乎是Base64所做的。它將二進制映射到字符串,但它並不是最優的,只能對它使用的每個字節進行6位編碼,從而使得生成的文件膨脹。但是,如果你僅僅使用ASCII字符串,這是最好的。 – bdares