文件压缩(哈夫曼压缩)
? 文件压缩总结(哈夫曼压缩)
?? 在学习哈弗曼压缩之前,还是首先来了解什么是哈夫曼树,哈夫曼编码。
?? 1.哈夫曼树是一种最优二叉树,它的带权路径长度达到最小。树的带权路径长度为所有叶子结点带权路径长度之和。
而结点的带权路径长度是结点的路径长度乘以结点的权值。
?? 2.哈夫曼编码是依据字符出现概率来构造异字头的平均长度最短的码字。从哈弗曼树的根结点开始,按照左子树代码为“0”,右子树代码为“1”的规则,直到树的叶子结点,每个叶子结点的哈弗曼编码就是从根结点开始,将途中经过的枝结点和叶子结点的代码按顺序串起来。
??
?? 哈夫曼压缩是字节符号用一个特定长度的01序列替代,在文件中出现频率高的符号,使用短的01序列,而出现频率少的字节符号,则用较长的01序列表示。
?? 这里的文件压缩,我还只能做简单的 文件A-->压缩为文件B--->解压为文件C,看文件A和文件C是不是相同。
那么就要分两个大步骤,小步骤:
? 不过,根据哈弗曼树的特点,我们首先还是要定义结点类型
?
rWrite(code,fHou); public void rWrite(String code,String fHou){ System.out.println("--->看不懂错误啊!!"); String path="D:\\1000\\A"+fHou; FileOutputStream fos; try { fos = new FileOutputStream(path);// 申明一个文件输出流 // 转成缓冲流 DataOutputStream dos = new DataOutputStream(fos); int m=1; //标志获取01 串的最后位置 String code2=""; //存储每次获得的原文件01 串的一个子集 while(code.length()>=m){ code2=code.substring(0,m);//获取当前01 字符串的 前m 位 System.out.println("???进来没?"+"-->"+code2); for(int j=0;j<codess.length;j++){ if(code2.equals(codess[j])){ byte b2=map.get(codess[j]); //由编码,获取他的 字节 System.out.println("--->"+(char)b2); dos.writeByte(b2); code=code.substring(m); m=0; System.out.println("code的长度为:"+code.length()); break; } } m++; } dos.close(); fos.close(); } catch (IOException e) { e.printStackTrace(); } } ?
?这里就基本上完成了文件的压缩和解压了。
遇到的困难:
????? 1.?之前建树是个大问题,因为建哈弗曼树涉及到了排序的问题,而每个结点又不是一个简单的数据类型,开始有尝试过队列和数组来实现排序的问题,但在实现过程中,遇到很大困难,原因还是前面那个,结点的类型比较复杂,在树形中当前结点交换位置影响到其孩子结点。开始还没意识到这个大问题,总是不能把树正确的搞出来,后来经龙哥指导才知道问题出在哪里。所有他建议使用优先队列,这个好啊,太方便了。不过,说实在话,这个优先队列在针对复杂的对象时,也还是要纠结一番啊,难懂。以后还要多多学习使用。
????? 2.?开始对码表的写入也很是纠结,觉得这是个大问题,很复杂,不知道怎么下手。后来经多次指点之前做过的画图板的保存的文件格式,类似完成码表的写入操作。
????? 3.?还只是单文件的压缩和解压,还不能实现大文件夹的压缩
遇到的问题还是很多,感觉还是基础太不扎实了,很多东西都不会用,而且总是不能有效利用前面学过的知识点,不能将所学系统联系起来。最要命的是特粗心,总是不注意细节,导致很多问题纠结很久,最后发现是出在小问题上。以后一定要特别注意这点。