簡體   English   中英

霍夫曼編碼完成后如何在Java中寫入文件

[英]How to write to a file in Java after Huffman Coding is done

我為霍夫曼編碼實現了一個類。 該類將解析一個輸入文件,並從中構建一個霍夫曼樹,並創建一個映射,該映射將出現在文件中的每個不同字符作為鍵,並將該字符的霍夫曼代碼作為其值。

例如,讓字符串“ aravind_is_a_good_boy”成為文件中的唯一行。 當您構建霍夫曼樹並為每個字符生成霍夫曼代碼時,我們可以看到,對於字符“ a”,霍夫曼代碼為“ 101”,對於字符“ r”,霍夫曼代碼為“ 0101”,依此類推。

我的意圖是壓縮文件。 因此,我無法將通過用霍夫曼代碼替換每個字符而創建的字符串直接寫到文件中。 因為,每個字符將至少替換為3個字符(每個“ 1”和“ 0”仍將作為字符而不是位寫入文件中)。 因此,我想我會將其作為字節寫入文件,因為無法將位寫入文件。 但是然后,“ a”和“ r”都被寫為“ 5”到文件中。 嘗試解壓縮文件時,這將導致問題。

這就是我將一系列位轉換為字節的方式:

public byte[] compressString(String s, CharCodeHashMap map) {
        String byteString = "";
        byte[] byteArr = new byte[s.length()];
        int size = 0;
        for (int i = 0; i < s.length(); i++) {
            byteString += addPaddingZeros(map.getCompressedChar(s.charAt(i)));
            byteArr[size++] = new BigInteger(byteString, 2).toByteArray()[0];
            byteString = "";
        }

        return byteArr;
    }

我嘗試為每個哈希碼添加前綴“ 1”,以解決此問題。 但是,當您構建霍夫曼樹並讀取文件時,某些字符將超過8位。 然后,問題是new BigInteger(byteString, 2).toByteArray()在數組中將有多個元素(例如,如果'v'具有哈希碼'11010001'和new BigInteger(byteString, 2).toByteArray()返回元素[0,-47]的數組。)

有人可以建議我一種寫文件的方法,這樣可以壓縮文件,同時也可以解決這些問題。

問題在於,現代操作系統中的文件被建模為字節1的可索引序列。

因此,您需要的是一種編碼以下事實的方式:文件表示的位數可能不是 8的倍數。這意味着位流大小不一定是文件大小(以字節為單位)乘以8。

有多種解決方案:

  • 在文件開頭保留N個字節,以字節為單位的文件大小。 例如,保留4個字節可使您表示最大2 2 32位的文件大小。
  • 在文件的開頭保留3位以保留模8的位數。您可以使用它來決定忽略文件最后一個字節中的多少位。
  • 使用某種編碼來表示流的結尾; 例如,將其表示為您正在編碼的文本流中的字符。

有沒有一種方法可以在使用某些位的情況下進行處理? AFAIK,不。


1-在較低級別,文件表示為由多個字節組成的磁盤塊序列。 因此,從物理存儲的角度來看,壓縮已經很小的文件(例如,小於磁盤塊的文件)並沒有任何效果。 類似地,如果將表示形式建模為字節序列,則保存或不保存(例如)3位將處於毫無意義的邊界……如果這與您有關。

是的,您可以將位寫入文件。 實際上,您總是在向文件寫入位。 唯一的事情是您一次寫入八個位。

您需要的是一個位緩沖區,例如一個32位無符號變量,您可以在其中存儲位。 還有另一個整數,該整數跟蹤位緩沖區中的多少位。 使用左移和/或(或加號)運算符將更多位放入位緩沖區,並使用和和右移運算符將其刪除。 只要位緩沖區中有八個或更多位,就將這八個位作為字節寫入文件。 最后,將剩余的位(如果有)作為最后一個字節寫入文件。

因此,要將值中的位添加到緩沖區中:

bitBuffer |= value << bitCount;
bitcount += bits;

寫入和刪除可用字節:

while (bitCount >= 8) {
    writeByte(bitBuffer & 0xff);
    bitBuffer >>>= 8;
    bitCount -= 8;
}

您需要確保在解碼時,不要將最后一個字節中的填充位誤認為另一個代碼。 您可以在消息之前發送消息中的實際位數(或最后一個字節中的位數),也可以在字母表中為流末尾添加符號,以獲取自己的霍夫曼代碼,並以此結束消息。

您遇到的另一個問題是,您還需要在編碼符號之前將霍夫曼代碼本身傳輸到解碼器,以使解碼器知道如何解碼。 查找“規范霍夫曼代碼”以了解如何有效地進行處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM