哈夫曼编码的时候,我们得到了哈夫曼哈希表、编码后的字节数组,我们根据这两个,便可以进行解码。
- 思路:
1、首先将字节数组转化为二进制字符串:
/**
* 将一个byte 转成一个二进制的字符串, 如果看不懂,可以参考我讲的Java基础 二进制的原码,反码,补码
* @param b 传入的 byte
* @param flag 标志是否需要补高位如果是true ,表示需要补高位,如果是false表示不补, 如果是最后一个字节,无需补高位
* @return 是该b 对应的二进制的字符串,(注意是按补码返回)
*/
private static String byteToBitString(boolean flag, byte b) {
//使用变量保存 b
int temp = b; //将 b 转成 int
//如果是正数我们还存在补高位
if(flag) {
temp |= 256; //按位与 256 1 0000 0000 | 0000 0001 => 1 0000 0001
}
String str = Integer.toBinaryString(temp); //返回的是temp对应的二进制的补码
if(flag) {
return str.substring(str.length() - 8);
} else {
return str;
}
}
2、根据哈夫曼哈希表,将二进制数组翻译成原字节数组(注:应该讲哈夫曼哈希表里的key和value翻转,这样才能依据二进制字符串得到字节数组):
//将赫夫曼编码的数据解码
@SuppressWarnings("unlikely-arg-type")
public static byte[] decode(Map<Byte, String> hfmMap,byte[] hfmbytes) {
System.out.println(Arrays.toString(hfmbytes));
//1、先得到赫夫曼编码对应的二进制字符串
StringBuilder stringBuilder = new StringBuilder();
boolean flage;
for (int i = 0; i < hfmbytes.length; i++) {
flage = (i == hfmbytes.length - 1);
stringBuilder.append(byteToBitString(!flage, hfmbytes[i]));
}
System.out.println(stringBuilder.toString());
//2、将赫夫曼哈希表key和value调换位置
Map<String, Byte> haspMap1 = new HashMap<String, Byte>();
for (Map.Entry<Byte, String> entry : hfmMap.entrySet()) {
haspMap1.put(entry.getValue()+"", entry.getKey());
}
System.out.println(hfmMap.toString());
System.out.println(haspMap1.toString());
//3、将二进制的哈夫曼编码用赫夫曼哈希表(key和value已经调换位置)解析
//byte[] bytes2 = new byte[];
List<Byte> list = new ArrayList<Byte>();
for(int i = 0; i < stringBuilder.length();) {
int count = 1;//指针
Byte byte1 = null;
while(true) {
String key = stringBuilder.substring(i,i+count);
byte1 = haspMap1.get(key);
if(byte1 == null) {//还未找到
count++;
}else {
break;
}
}
list.add(byte1);
i += count;
}
byte[] bytes2 = new byte[list.size()];
for (int i = 0; i < bytes2.length; i++) {
bytes2[i] = list.get(i);
}
return bytes2;
}
3、打印字节数组成字符串即可:
byte[] d = decode(hashMap, byte1);
System.out.println(new String(d));
- 问题:
我发现如果哈夫曼编码后的二进制字符串如果最后的子字符串不满8位时,若为0111,则直接转化为了7,但是再次解码时,7被解码成了111,此时0便消失不见了,所以有的时候,哈夫曼解码时会有问题(尾部少数据)。