本文共 2160 字,大约阅读时间需要 7 分钟。
霍夫曼编码的应用——压缩文件
二进制的补码,反码,以及原码之间的关系
- 原码:正数的原码:按照二进制转换成二进制码就是原码。负数的原码:其对应的绝对值转换成二进制原码后,在高位补一。
- int类型的1,在32位机器上,占有的四个字节,高位补零。得到:00000000 00000000 00000000 00000001
- int类型的-1,在32位机器上,占有四个字节,取绝对值,高位补一。得到:10000000 00000000 00000000 00000001
- 反码:正数的反码就是原码,负数的反码是原码除符号位以外所有的位取反。
- int类型的1,在32位机器上,其反码为原码,高位补零。得到:00000000 00000000 00000000 00000001
- int类型的-1,在32位机器上,其反码为符号位不变,其余取反。得到:11111111 11111111 11111111 11111110
- 补码:正数的补码与原码相同,负数的补码为在反码的基础上在最低位再加1
- int类型的1,补码,反码,与源码相同。补码为:00000000 00000000 00000000 00000001
- int类型的-1,在反码的基础上,与最低位加一。补码为:11111111 11111111 11111111 11111111
- 总结:
- 正数,三个码相同,原码,反码,和补码相同。
- 负数:
- 原码是其绝对值对应的原码,在最高位上取1.
- 反码:是在负数的原码的基础上,除了符号位不变,其余都取反
- 补码:是在反码的基础上,在最低位加1,就得到补码。
压缩的理解
- 文件的原始存储方式,将原来的字符串转成字节,按照对应ASCII码,有多少个字符就有多少个byte元素。
- 压缩文件的处理方式,先将数据进行处理,根据每一个字符出现的次数进行编码,形成一新的编码标,霍夫曼编码,然后根据编码将所有的字符转成二进制,然后八个一组转成对应的byte数组,进行存储。
用生成的霍夫曼编码的处理数据
public static byte[] zip(byte[] bytes,Map huffmanCodes){ StringBuilder stringBuilder = new StringBuilder(); for (byte ch:bytes){ stringBuilder.append(huffmanCodes.get(ch)); } System.out.println(stringBuilder.toString()); //将上述的字符串转成byte数组 //统计返回byte【】,huffmanCodeByte的长度 int len; if (stringBuilder.length() % 8 == 0){ len = stringBuilder.length() / 8; }else{ len = stringBuilder.length() / 8 + 1; } //创建存储压缩之后的byte数组 byte[] huffmanCodeByte = new byte[len]; int index = 0; for (int i = 0;i < stringBuilder.length();i += 8){ String string; if (i + 8 > stringBuilder.length()){ string = stringBuilder.substring(i); }else{ string = stringBuilder.substring(i,i + 8); } huffmanCodeByte[index] = (byte)Integer.parseInt(string,2); index ++; } return huffmanCodeByte; }
分析与总结:
- 我们在将由霍夫曼加工过的生成的二进制数的代码八个一组转成byte数组的成员时,如果不足八位,左边用0补齐,那么再解压的时候,不久多了很多的零,那么还怎么能正常的解压?
- 我们常说的压缩率仅仅指的是将文件压缩后的大小和原始文件大小进行比较,但是没有将对应形成的霍夫曼编码表放到文件中去,所以我认为,应该在已经形成的文件后面加上对应的霍夫曼编码表,以确保能顺利解压。
常见问题
- 忽略index++的结果,除了第一项,其余的都是零,没有赋值,都是默认值
转载地址:http://lqgpb.baihongyu.com/