`

哈夫曼压缩总结

 
阅读更多
哈弗曼压缩
哈弗曼压缩过程梳理
步骤
读入文件。统计字节出现的次数(可以得到数组里面的次数还有该对应的下标)
将要读入的文件一个字节一个字节的读入,然后创建一个数组,数组的下标与该字符的ASCII码值相对应,当出现一次该字符的时候,拥有该下标值的数组加一。
while (fis.available() > 0) {// 当文件还有字节没被读取,继续循环
int i = fis.read();
// 每次读取的都是一个字节,正好是一个ascii码值,也正好是countByte下标
countByte[i]++;// 次数加一
对该数组进行排序。(返回的是一个树的根节点,也就是队列只剩下一个时的节点)
在优先队列(优先队列里面储存的是节点)里面添加该数组,并进行排序。然后建哈弗曼树。每次都从队列中选两个最小值的节点,小的作为右节点,大的作为左节点,新建一个父节点,对他们进行设置后,把该父节点放进队列里面重新进行排序。重复此操作,当队列只剩一个时,该树建立完成。
// 实例化一个优先队列
PriorityQueue<HfmNode> nodeQueue = new PriorityQueue<HfmNode>();
for (int j = 0; j < countByte.length; j++) {
// 循环数组,让每个出现的ascii码值全都遍历到,长度是256
if (countByte[j] != 0) {
// 当有该ascii码值出现的时候,把带有ascii码值和出现次数的节点加入到队列中
HfmNode node = new HfmNode(j, countByte[j]);
// 新建一个节点带有ascii码值出现的次数和ascii码
nodeQueue.add(node);// 把该节点加入到优先队列中去
}
}
 HfmNode min1 = nodeQueue.poll();
HfmNode min2 = nodeQueue.poll();
// 新建一个节点,作为min1和min2的父节点,他的出现次数是两个相加
HfmNode result = new HfmNode(0, min1.gettimes() + min2.gettimes());
然后返回root,这棵哈弗曼树就建好了。
对每个哈弗曼树的叶子节点设置对应的哈弗曼编码
遍历每个叶子节点,然后向左走就是0;往右子树走的话就在字符串上加1。然后就可以把叶子节点的所对应的01串与数组下标进行匹配。也相当于AscII值所对应的字符与01串相对应。
public void getMB(HfmNode hfm, String str) {
if ((hfm.getLchild() == null) && (hfm.getRchild() == null)) {
// 当该节点是叶子节点的时候
Code code = new Code();
code.setNode(str);// 设置节点的01字符串
code.setN(str.length());// 设置01字符串的长度

SaveCode[hfm.getData()] = code;
  / /每个叶节点的ascii码所对应的编码(01字符串)
}
if (hfm.getLchild() != null) {
getMB(hfm.getLchild(), str + "0");// 往左边走就是写0
}
if (hfm.getRchild() != null) {
getMB(hfm.getRchild(), str + "1");// 往右边走写1
}
}
写文件:1.头文件
写每个编码的长度(对应有几个字节)
写每个编码与之所对应的字符(由于编码可能不足八位或者超过八位,不足八位的则补0补到八位,超过八位则补0补到八的整数倍位)

/**
* 该方法是字节补0,每个ascii码值对应的哈弗曼编码长度可能不足八位,或者超过八位
* 所以要给长度补到8的倍数
* zijienode【】保存的是每个ascii码补0 后的01串字符 zijiesize【】保存的是每个ascii码* 补到八位后的长度
*/
public void zijiebu0() {
for (int i = 0; i < SaveCode.length; i++) {
if (SaveCode[i] != null) {
// 当savecode里面储存的不为空,里面存的是code,code存的是哈弗曼编码和长度
zijienode[i] = SaveCode[i].getNode();
int bytesize = 8 - SaveCode[i].getN() % 8;// 求需补多少0
if(bytesize==8){
bytesize=0;
}
int size = bytesize;
if (bytesize > 0) {// 当余数大于0
while (bytesize > 0) {
// SaveCode[i].setNode(SaveCode[i].getNode()+"0");//给哈弗曼编码补上一个0
zijienode[i] = zijienode[i] + "0";// 给哈弗曼编码补上一个0
bytesize--;// 循环次数减一
}
}
zijiesize[i] = (SaveCode[i].getN() + size) / 8;
// 把取得的ascii码值的哈弗曼编码设置字节长度
System.out.println("字符" + (char) i + "的哈弗曼编码为:" + zijienode[i]
+ "他的长度为" + zijiesize[i]);
}
}
}
现在已经得到了字节补0后的哈弗曼编码和字节的长度,这样就可以把码表给写进去
// 先把码表都给读入进去
for (int i = 0; i < countByte.length; i++) {
if (countByte[i] != 0) {// 当又出现ascii码值的下标的数组时,读入
try {
fos.write(i);// 先把每个ascii码给写进去
fos.write(zijiesize[i]);
//把每个ascii码值对应的补0后的哈弗曼编码的长度也写进去
int bu0=zijiesize[i] * 8 - SaveCode[i].getN();
fos.write(zijiesize[i] * 8 - SaveCode[i].getN());// 再把每个ascii码值所补0的个数写进去
System.out.println("========哈弗曼编码补零个数:"+bu0 );
// 因为每次读入的是int型,读八位,所以如果大于八位的那就循环每次读八位
int k = 8;
int z = zijiesize[i];
while (z > 0) {// 当哈弗曼编码的长度大于8,则先读前八位
String ss = "";
for (int j = k - 8; j < k; j++) {// 每次都循环八次
ss += zijienode[i].charAt(j);// 把要读入的ss先写好八位
}
k += 8;// 继续加上八位
fos.write(changeString(ss));
System.out.println("=======哈弗曼编码为:"+ss );
z -= 1;// 每次读完八位后,就在哈弗曼长度-1
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
书写好码表之后,就开始书写文件补0的个数
书写文件内容
把文件内容一个字节一个字节的读入到指定的文件位置,因为文件内容此时是每个字符对应的哈弗曼编码,加起来位数可能不足八位。如果不足八位,则在后面补0补到八位。
FileInputStream fis = new FileInputStream(newpath);// 实例话一个输入流,把文件内容读写进来
String str = "";
try {
while (fis.available() > 0) {// 当文件还有字节没有读取的时候则执行循环
int i = fis.read();// 读取每一个字节
str += SaveCode[i].getNode();// 把哈弗曼编码加上去
while (str.length() > {
// 当加起来的哈弗曼编码长度大于八,则执行循环,若小于或等于8,则加上后来的哈弗曼//编码
String str1 = "";// 要输入的哈弗曼编码
for (int j = 0; j < 8; j++) {// 每次写进去一个字节长度的哈弗曼编码
str1 += str.charAt(j);
}
fos.write(changeString(str1));
// System.out.println("输入内容啦输入内容啦!!!");
for (int j = 8; j < str.length(); j++) {
  // 然后把前八位的哈弗曼编码去掉
str = "" + str.charAt(j);
}
}
}
// 当文件没有文件内容可读入的时候且这时候还有哈弗曼编码没有写进去时,判断是否是一个字节的长度或者不是一个字节的长度,不够的则补0后写入
if (str.length() == {
fos.write(changeString(str));
}
if (str.length() < {
int c = 8 - str.length();
for (int d = 0; d < c; d++) {
str += "0";
}
fos.write(changeString(str));
}
解压缩和压缩正好是逆过程
思路:
先读取码表长度,得到码表的长度后,在循环读取码表的ascii码值,ascii码值对应的哈弗曼编码长度,补零情况,然后读取补0后的哈弗曼编码,然后把哈弗曼编码去掉补的0,把哈弗曼与ascii码值相对应起来,用数组存。
读取码表与文件内容补零情况
  for (int a = 0; a < mabiaosize; a++) {
int i = fis.read();// 先读取ascii码值
System.out.println("ascii码值为:" + (char) i);
int zijiesize = fis.read();// 获得字节长度的大小
System.out.println("字节长度为:" + zijiesize);
int bu0 = fis.read();// 读取补0的情况
System.out.println("字节补零个数" + bu0);
String str = "";
for (int j = 0; j < zijiesize; j++) {// 开始循环取得哈弗曼补0后的编码
str += int_to_String(fis.read());// 把字符串给写进来
}
// 然后开始根据补0的个数来去掉0
String hfmcode1 = "";
for (int j = 0; j < zijiesize * 8 - bu0; j++) {
hfmcode1 += str.charAt(j);
}
hfmcode[i] = hfmcode1;// 根据取得的字符串和ascii编码进行匹配
System.out.println((char) i + "字符的哈弗曼编码是:" + hfmcode[i]);
}
int neirongbu0 = fis.read();// 读取文件内容补零的情况
System.out.println("字节补零个数 " + neirongbu0);
然后读取完码表后,开始读取文件内容
  String file_01="";
while(fis.available()>1){
int count_writed_01=0;
//读取的01字符串
file_01+=int_to_String(fis.read());
//System.out.println("源文件的01串是:"+file_01);
int k=0;
int count=1;
while(count<=file_01.length()){
//定义哈夫曼编码变量
String HFMcode="";
for(int i=k;i<count;i++){
HFMcode+=file_01.charAt(i);
}
for(int i=0;i<hfmcode.length;i++){
if(hfmcode[i]!=null&&hfmcode[i].equals(HFMcode)){
//System.out.println("哈夫曼编码是"+HFMcode);
count_writed_01+=HFMcode.length();
//System.out.println("写入了"+count_writed_01+"个");
k=count;
fos.write(i);
//System.out.println("内容写入了"+i);
}
}
count++;
}
//System.out.println("写入后的file_01是"+file_01);
String file_01x="";
for(int i=count_writed_01;i<file_01.length();i++){
file_01x+=file_01.charAt(i);
}
file_01=file_01x;
//System.out.println("清空后的file_01是"+file_01);
}
  //读取最后一个字符串
String str_end=file_01+int_to_String(fis.read());
//System.out.println("最后一个字符串是"+str_end);
int file__0=yasuo.getFile_0();//获取问价末尾补0个数
//把最后读取的字符串补的0去掉
String str="";
for(int i=0;i<str_end.length()-file__0;i++){
str+=str_end.charAt(i);
}
str_end=str;
//System.out.println("把0删掉后变成:"+str_end);
int count=1;
int k=0;
while(count<=str_end.length()){
str="";
for(int i=k;i<count;i++){
str+=str_end.charAt(i);
}
//System.out.println("str是:"+str);
for(int i=0;i<array.length;i++){
if(array[i]!=null&&array[i].equals(str)){
//System.out.println("&&&&&&&&&&&");
fos.write(i);
k=count;
}
}
count++;
}
如此一来,哈夫曼压缩就完成了!!
分享到:
评论

相关推荐

    哈夫曼压缩与解压文件课程设计(代码+实习报告)

    哈夫曼编码是一种高效的数据压缩方法,由大卫·哈夫曼在1952年提出。它是基于一种称为哈夫曼树(也叫最优二叉树)的数据结构。在这个课程设计中,你将深入理解哈夫曼编码的原理,并通过C++编程语言实现文件的压缩与...

    哈弗曼压缩总结

    总结,哈弗曼压缩是一种基于频率的编码方法,它通过构建哈弗曼树来实现对数据的有效压缩。在Java中,可以通过分析给定的源码文件了解并实现这一过程,这有助于提高对数据压缩原理和算法的理解。

    哈夫曼树压缩算法实现

    总结来说,哈夫曼树压缩算法利用了数据的统计特性,通过构建最优二叉树实现高效的数据编码,进而完成数据的压缩。在实际应用中,这种算法广泛应用于文本、图像和音频等数据的压缩,提高了存储和传输的效率。

    哈夫曼压缩技术

    总结来说,哈夫曼压缩技术是一种基于频率的无损数据压缩方法,特别适合处理包含重复元素的数据。虽然在处理图像压缩时可能效率较低,但与其他算法结合使用时,如EZW,可以提升压缩效果。在实际应用中,哈夫曼编码常...

    哈夫曼压缩算法步骤,请参考具体的内容

    哈夫曼编码是一种高效的数据压缩编码技术,由美国科学家大卫·哈夫曼在1952年提出。这种编码方式是基于信源符号的概率分布,通过构建最优的二叉树来实现,使得出现频率高的符号拥有较短的编码,而出现频率低的符号...

    利用哈夫曼编码压缩文件的小工具

    总结来说,这个小工具通过哈夫曼编码技术实现了文件的压缩和解压缩,利用了数据的频率特性,尤其适用于那些含有大量重复字符的文件。同时,哈夫曼编码的原理和实现也是计算机科学中经典的数据压缩理论,对于理解和...

    哈夫曼算法实现任意文件格式的压缩解压

    在哈夫曼压缩与解压软件的实现中,MFC提供了图形用户界面(GUI)的构建基础,包括对话框、控件和文件操作类,使得开发者能够更加专注于算法的实现,而无需过多关注底层的Windows API。 哈夫曼编码的核心步骤包括: ...

    哈夫曼树实现文件压缩

    总结起来,哈夫曼树和小顶堆在文件压缩中的应用是一项高效的技术,通过优化编码长度,有效减少了文件大小。在实现过程中,理解并掌握这两个数据结构的操作是至关重要的。通过FileCompress.h、Heap.h和HaffmanTree.h...

    xsjl.rar_Java哈夫曼编码_哈夫曼_哈夫曼 编码_哈夫曼压缩

    总结来说,Java哈夫曼编码是利用数据结构和算法理论实现的一种压缩技术,它在处理大量重复字符的数据时表现优秀。通过合理地分配编码长度,哈夫曼编码可以有效地减少存储空间,同时保持数据的可恢复性,因此在文本...

    HuffmanCompress_编码_哈夫曼压缩算法_

    在实际的哈夫曼压缩过程中,我们先遍历输入文件中的每个字符,根据哈夫曼编码表将其转换为二进制序列,然后将所有二进制序列连接起来形成一个大的二进制串。这个二进制串就是压缩后的文件,可以写入到名为"2文件"的...

    哈夫曼压缩

    总结来说,哈夫曼压缩是一种高效的无损数据压缩方法,基于字符频率构建特殊的二叉树并生成前缀编码。它在数据存储、传输和各种文件格式中都有广泛应用,并可以通过各种编程工具和库进行实现和操作。

    哈夫曼编码压缩解压文件

    总结来说,哈夫曼编码是一种基于字符频率的压缩技术,它通过构建哈夫曼树并生成编码来实现数据压缩。在“哈夫曼编码压缩解压文件”的过程中,理解哈夫曼树的构建、编码的生成以及压缩和解压的步骤至关重要。掌握这些...

    压缩软件(哈夫曼算法实现) 项目总结

    《哈夫曼编码在压缩软件中的应用与实现》 哈夫曼编码,作为一种高效的数据压缩方法,被广泛应用于各类压缩软件中。它基于频率最小的编码原则,通过构建最优的二叉树结构来实现对数据的高效编码。在这个项目中,我们...

    java哈夫曼压缩和解压

    总结,Java哈夫曼压缩和解压涉及对数据编码、构建哈夫曼树、生成编码表、解码等过程,通过高效的数据结构和算法实现高效的数据压缩。了解和掌握哈夫曼编码不仅有助于理解数据压缩原理,也是提升软件开发效率的重要...

    哈夫曼编码法的压缩和解压缩

    总结来说,哈夫曼编码是一种基于字符频率的无损数据压缩方法,通过构建哈夫曼树来生成编码,并据此进行数据的压缩和解压缩。在VC环境下,可以编写C++程序来实现这一过程,从而提高数据存储和传输的效率。

    利用C++实现哈夫曼算法

    总结来说,利用C++实现哈夫曼算法,需要对哈夫曼树的构建、节点的管理以及编码和解码的过程有深入的理解。通过构建一个按照字符频率排序的哈夫曼树,可以得到一个有效的数据压缩方案。掌握这一算法不仅能够帮助我们...

    哈夫曼压缩解压数据结构设计报告样本.doc

    《哈夫曼压缩解压数据结构设计》报告 在数据处理和存储中,文献压缩是一种重要的技术,旨在减少数据的存储需求。哈夫曼编码是一种高效的数据压缩方法,基于字符出现频率进行编码,使得出现频繁的字符具有较短的编码...

    哈夫曼编码压缩解压缩软件课程设计报告

    哈夫曼编码是一种高效的数据压缩方法,主要用于无损数据压缩,其原理基于频率最小的字符用最短的编码,频率最高的字符用最长的编码。在本课程设计中,学生将深入理解并应用哈夫曼编码的理论,实现一个能够进行压缩...

    哈夫曼压缩解压-大数据结构设计报告材料.doc

    总结来说,哈夫曼压缩解压缩是通过构建哈夫曼树,根据字符出现的频率为其分配不同的二进制编码,从而实现文件的高效压缩和解压缩。在具体实现时,需要设计合适的数据结构和算法来支持这一过程,同时保证压缩前后文件...

    Java哈夫曼编码的文件的压缩与解压.docx

    在Java编程中,哈夫曼编码(Huffman Coding)是一种数据压缩算法,它基于字符出现频率构建最优前缀树(也称为哈夫曼树),从而为每个字符分配一个唯一的二进制编码。这个编码方法使得频繁出现的字符拥有较短的编码,...

Global site tag (gtag.js) - Google Analytics