【发布时间】:2023-03-22 13:32:02
【问题描述】:
我正在尝试解码霍夫曼代码。
我有一个字符字典,有一个 int 值和一个二进制值以及单词的二进制值,它看起来像这样:
10,000; 121,001; 13,010; 33,011; 100,1000; 32,1001; 104,1010; 101,1011; 111,1100; 108,1101; 119,1110; 114,1111101100111010000
...其中10 - 121 -13 -33等数字是字符的int值,旁边是char的二进制值,然后1和0的序列是代码消息。
从文件 txt 中读取它后,我将其拆分为字符串数组,这样我就可以得到一个以 char 作为键、二进制值作为值的 hashmap。
然后我将它保存在一个节点数组中,这样我就可以轻松获取它们了,问题是这样的:
当我尝试使用字典将二进制消息转换为 char 时,我收到如下消息:
1!y1y111!y11111!
什么时候应该这样:
嘿,世界!!
这是我正在使用的方法:
void decompress() throws HuffmanException, IOException {
File file = FilesManager.chooseUncompressedFile();
if (file == null) {
throw new HuffmanException("No file");
}
FileReader read = new FileReader(file);
BufferedReader buff = new BufferedReader(read);
String auxText;
StringBuilder compressFromFile = new StringBuilder();
do {
auxText = buff.readLine();
if (auxText != null) {
compressFromFile.append(auxText);
}
} while (auxText != null);
String[] auxSplit1 = compressFromFile.toString().split(" ");
String rest1 = auxSplit1[1];
String[] auxSplit2 = rest1.split(";");
System.out.println(auxSplit2[2]);
HashMap<Integer, String> map = new HashMap<>();
String[] tomapAux;
for (int i = 0; i < auxSplit2.length - 2; i++) {
tomapAux = auxSplit2[i].split(",");
map.put(Integer.valueOf(tomapAux[0]), tomapAux[1]);
}
ArrayList<CharCode> charCodeArrayList = new ArrayList<>();
map.forEach((k, v) -> charCodeArrayList.add(new CharCode((char) k.intValue(), v)));
charCodeArrayList.sort(new Comparator<CharCode>() {
@Override
public int compare(CharCode o1, CharCode o2) {
return extractInt(o1.getCode()) - extractInt(o2.getCode());
}
int extractInt(String s) {
String num = s.replaceAll("\\D", "");
return num.isEmpty() ? 0 : Integer.parseInt(num);
}
});
for (int i = 0; i < charCodeArrayList.size(); i++) {
System.out.println("Pos " + i + " char: " + charCodeArrayList.get(i).getChr() + " code: " + charCodeArrayList.get(i).getCode());
}
String st = auxSplit2[auxSplit2.length - 1];
System.out.println("before: " + st);
String newChar = String.valueOf(charCodeArrayList.get(0).getChr());
String oldChar = charCodeArrayList.get(0).getCode();
for (CharCode aCharCodeArrayList : charCodeArrayList) {
st = st.replace(oldChar, newChar);
newChar = String.valueOf(aCharCodeArrayList.getChr());
oldChar = aCharCodeArrayList.getCode();
}
System.out.println("after : " +st);
}
这是CharCode类:
public class CharCode implements Comparable<CharCode> {
private char chr;
private String code;
public CharCode(char chr, String code) {
this.chr = chr;
this.code = code;
}
public char getChr() {
return chr;
}
public String getCode() {
return code;
}
@Override
public int compareTo(CharCode cc) {
return ((int) this.chr) - ((int) cc.getChr());
}
}
这就是我在控制台中看到的:
因此,如果有人可以帮助我改进我的方法,以便我可以得到 hey world!! 而不是 1!y1y111!y11111! !!01,那就太好了!
【问题讨论】:
-
在填充地图的循环中:为什么使用
for (int i = 0; i < auxSplit2.length - 2; i++)而不是for (int i = 0; i < auxSplit2.length - 1; i++)?您正在跳过最后一个霍夫曼代码 -
@mangusta 我使用它,所以我可以将
10,000;121,001;13,010;33,011;etc;与10101011001100111101100111111011000011011010000分开 -
index of this:
10101011001100111101100111111011000011011010000是auxSplit2.length-1,前面的其他都是霍夫曼代码,所以你的循环条件必须是for (int i = 0; i < auxSplit2.length - 1; i++) -
@mangusta 是的,我用它来分隔字符串“父亲”,所有这些都在同一个句子中,然后
10,000;121,001;13,010;33,011;etc;我将它保存在 CodeChar 的地图中,它就像我看到一个 10 然后一个 000 一样工作,所以我将 int 10 保存为键,将 000 保存为映射中的字符串值 -
我不确定你在说什么,但你肯定需要按照我告诉你的方式改变循环条件
标签: java file huffman-code