I'm trying to decode a Huffman code.
I got a dictionary of chars, with an int value and a binary value of it and the binary values of the words, and it looks like this:
10,000;121,001;13,010;33,011;100,1000;32,1001;104,1010;101,1011;111,1100;108,1101;119,1110;114,1111;10101011001100111101100111111011000011011010000
... where the numbers like 10 - 121 -13 -33
and others are int values of a character, next to them are the binary value of the char, and then the sequence of 1 and 0 are the code message.
After I read it from a file txt, I split it in strings array so I can have a hashmap with the char as a key and the binary value as value.
Then I save it in an array of nodes so I can take them easily, the problem is this:
When I try to convert the binary message to char using the dictionary, I get a message like this:
1!y1y111!y11111!
When it should be this:
hey world!!
This is the method I'm using:
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);
}
And this is the class 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());
}
}
And this is what I see in the console:
So if anyone can help me on improving my method so I can get a hey world!!
and not 1!y1y111!y11111! !!01
, that would be great!