解压就是压缩的逆过程……真是说起来容易做起来难啊……
不过最后还是做出来了,而且发现了前面的压缩函数的几个问题:
1.编码区不用存入补的零的个数:因为解压的时候是按照每个编码的长度截取的,所以到最后剩下的另不会造成任何影响,这样就不用再把补的零写进去了
2.从输入流读取数据的顺序要注意:比如下面是我昨天的代码
/************************ 再次读入文件信息,对应每一个字节写入编码 *********************/
// 再次读入文件信息,对应每一个字节写入编码
// 用来读取数据的文件输入流
FileInputStream ins = new FileInputStream(path1);
// 包装成缓冲流
BufferedInputStream bis = new BufferedInputStream(ins);
count = 0;
writes = "";
tranString = "";
int idata = bis.read(); //就是这行错了…************************
// 文件没有读完的时候
while ((bis.available() > 0) || (count >= 8)) {
// 如果缓冲区等待字符大于等于8
// System.out.println(count+"<<>>"+writes.length());
if (count >= 8) {
waiteString = "";// 清空要转化的码
for (int t = 0; t < 8; t++) {
waiteString = waiteString + writes.charAt(t);
}
// 删除前八位
writes = writes.substring(8);
count -= 8;// 写出一个8位的字节
int intw = changeString(waiteString);
bos.write(intw);// 写入到文件中
bos.flush();
} else {
// 读入idata字节 ,对应编码写出信息
count += SaveCode[idata].getN();
writes += SaveCode[idata].getNode();
// System.out.println(SaveCode[idata].getN()+"<<>>"+SaveCode[idata].getNode().length());
idata = bis.read();
}
}
count += SaveCode[idata].getN();
writes += SaveCode[idata].getNode();
// 把count 剩下的写入
int endsint = 0;
if (count > 0) {
waiteString = "";// 清空要转化的码
for (int t = 0; t < 8; t++) {
if (t < writes.length()) {
waiteString += writes.charAt(t);
} else {
waiteString += '0';
endsint++;
}
}
// System.out.println(waiteString.length());
bos.write(changeString(waiteString));// 写入最后补的0
bos.flush();
bos.write(endsint);// 写入最后补的0的个数
bos.flush();
System.out.println("压缩区写入了->" + endsint + "个0");
}
}
那个被我重点标出来的一行用该写在下面的else里面,不然会出现解压以后丢失最后一个字节的错误(修了半天才修好的……)
编程序的时候一定要理清思路啊……不然一点错了,就要重新检查……费时费力啊……
还有解压的时候,系统自带的 八十进制转化为二进制的函数Integer.toBinaryString(int i) 它转化成的01字符串如果是以0开头的话,会自动把0删掉,这样会造成我们的编码丢失,所以要修改一下,把它删除的0再补回来~~~
这样整个哈夫曼压缩和解压都完成了~下面这张图就是压缩的效果~哈~完工~(源文件有很多重复)
下面放出我的解压代码:
package 哈夫曼压缩;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
public class LoadFile {
private String path;
private String path1;
private Code ReadCode[] = new Code[256];
public LoadFile(String path, String path1) {
this.path = path;
this.path1 = path1;
}
public void realease() throws IOException {
FileInputStream fis = new FileInputStream(path);
BufferedInputStream bis = new BufferedInputStream(fis);
// 读取每个字节的编码长度
for (int i = 0; i < ReadCode.length; i++) {
Code a = new Code(bis.read(), null);
ReadCode[i] = a;
// if (ReadCode[i].getN() != 0)
// System.out.println("字节" + i + "的编码长度为:" + ReadCode[i].getN());
}
String writes = "";// 转化成01串的字符串
String waitString = "";
// writes+=changeInt(bis.read());
for (int i = 0; i < ReadCode.length; i++) {
while (writes.length() < ReadCode[i].getN()) {
writes += changeInt(bis.read());
}
waitString = "";
// 按照每个字节的编码长度读取字符串
for (int j = 0; j < ReadCode[i].getN(); j++) {
waitString += writes.charAt(j);
}
ReadCode[i].setNode(waitString);
waitString = "";
// 移除已经写入的数据
writes = writes.substring(ReadCode[i].getN());
}
// 创建映射
HashMap<String, Integer> map = Setmap(ReadCode);
/************ 读取文件信息,转换成原来的数据写入文件 *****************/
writes = "";
waitString = "";
// 创建文件输出流
FileOutputStream fos = new FileOutputStream(path1);
BufferedOutputStream bos = new BufferedOutputStream(fos);
while (bis.available() > 2) {
writes = writes + changeInt(bis.read());// 先读取一串01串
// System.out.println("待检查的字符串为:" + writes);
for (int i = 0; i < writes.length(); i++) {
waitString += writes.charAt(i);
if (map.containsKey(waitString) == true) {
bos.write(map.get(waitString));
bos.flush();
// System.out.println("写入了" + waitString + "<>字节"
// + (char) (int) map.get(waitString));
// System.out.println("编码长度为" + waitString.length());
writes = writes.substring(waitString.length());
// System.out.println("剩下的字符串为:" + writes);
waitString = "";
i = -1;
}
}
waitString = "";
}
System.out.println("还剩下:" + bis.available());
String last = changeInt(bis.read());
int ls = bis.read();
System.out.println("补了" + ls + "个0");
// 去除最后几个0
String temp;
temp = last;
last = "";
for (int i = 0; i < 8 - ls; i++) {
last += temp.charAt(i);
}
writes += last;
System.out.println("待检查的字符串为:" + writes);
for (int i = 0; i < writes.length(); i++) {
waitString += writes.charAt(i);
if (map.containsKey(waitString) == true) {
bos.write(map.get(waitString));
bos.flush();
System.out.println("写入了" + waitString + "<>字节"
+ (char) (int) map.get(waitString));
// System.out.println("编码长度为" + waitString.length());
writes = writes.substring(waitString.length());
System.out.println("剩下的字符串为:" + writes);
waitString = "";
i = -1;
}
}
}
// 创建映射
public HashMap<String, Integer> Setmap(Code[] a) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
for (int i = 0; i < a.length; i++) {
map.put(a[i].getNode(), i);
}
return map;
}
/**
* 将一个整数转化为八位字符串
*
* @param s
* @return
*/
public String changeInt(int i) {
String s = Integer.toBinaryString(i);
if (s.length() < 8) {
int bu = 8 - s.length();
String temp = s;
s = "";
for (int i1 = 0; i1 < bu; i1++) {
s += '0';
}
s += temp;
}
// System.out.println("读出的字符串为:\t" + s);
return s;
}
}
- 大小: 131.3 KB
分享到:
相关推荐
在"哈夫曼实现压缩解压缩——源代码"中,我们可以期待看到一个用C语言在Linux环境下实现的哈夫曼编码和解码过程。 哈夫曼编码的过程主要包括以下步骤: 1. **构建哈夫曼树**:首先,统计所有字符的出现频率,创建...
哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩...
总之,哈夫曼压缩解压缩是数据压缩领域的一个重要方法,通过MFC和VC++,我们可以构建出直观且高效的压缩工具,便于学习和研究。在这个过程中,理解哈夫曼编码的原理、掌握MFC的使用以及实现压缩和解压缩的算法,都是...
哈夫曼编码压缩解压文件源代码 哈夫曼编码是一种变长前缀编码方案,用于压缩数据。哈夫曼树是一种特殊的二叉树,它的每个叶子结点对应一个字符,而每个内部结点对应一个符号的频率信息。哈夫曼编码的基本思想是:将...
总的来说,哈夫曼压缩解压缩的Java代码涉及到了数据结构(二叉树、优先队列)、编码理论、文件I/O以及错误处理等多个方面的知识。理解和实现这一过程有助于深入理解数据压缩原理,提高编程能力。
哈夫曼编码是一种高效的数据编码方法,主要用于无损数据压缩,尤其在文本文件的压缩中表现出色。这种编码方式基于频率最小的字符用最短的二进制代码表示的原理,能够有效地减少数据存储和传输时的位数,从而达到压缩...
哈夫曼解压缩程序,通常被称为Szip,是一种基于哈夫曼编码的高效数据压缩算法。在信息技术领域,数据压缩是存储和传输信息的关键技术,它通过减少数据冗余来节省存储空间和提高传输效率。哈夫曼编码是数据压缩中的...
《哈夫曼编码压缩解压缩程序的实现及原理》 哈夫曼编码是一种高效的数据压缩方法,它基于字符出现频率构建最优的二叉树结构,从而实现数据的压缩与解压缩。本文将深入探讨哈夫曼编码的原理,并通过一个使用C++编写...
mypage文件可能包含了实现哈夫曼压缩和解压缩算法的C源代码文件,以及相关的测试数据或结果。通过阅读和理解这些代码,你可以深入学习哈夫曼编码的工作原理,以及如何在C语言中实现这一算法。同时,还可以了解到如何...
文件列表中的`huffman.c`是源代码文件,包含了哈夫曼压缩和解压缩算法的实现,而`huffman.exe`是编译后的可执行文件,可以直接运行进行压缩和解压缩操作。在实际使用中,用户可能需要提供待压缩的文件作为输入,然后...
总的来说,这款“利用哈夫曼原理的压缩解压缩软件”结合了哈夫曼编码的高效压缩算法和MFC的用户界面设计,为用户提供了一种便捷且直观的文件压缩和解压缩工具。其核心在于哈夫曼编码的优化和MFC的UI实现,确保了压缩...
哈夫曼实现文件的压缩与解压缩,代码关键部分有注释。
这个项目“哈夫曼压缩——GUI”是基于Visual Studio 2010开发的一个图形化界面工具,对于学习数据结构和算法的学生来说,是一个很好的实践案例。 1. **哈夫曼编码**:哈夫曼编码是一种变长的前缀编码方式,通过构建...
通过阅读和理解这些源代码,你可以更深入地了解哈夫曼压缩的具体实现细节,包括如何构建和操作哈夫曼树,以及如何有效地进行编码和解码操作。学习这部分内容对于理解和实现数据压缩算法,优化文件存储和传输效率具有...
`SRC`文件可能包含了C++源代码,展示如何构建哈夫曼树、生成编码、压缩和解压数据的具体实现。`DOC`文件可能是实验报告,详细解释了这些过程并分析了算法的效率。`EXE`文件则可能是编译后的可执行程序,可以直接运行...
在Java编程环境中实现哈夫曼压缩与解压缩程序,我们可以利用面向对象的特性,设计多个类来完成不同部分的功能。 1. **FileChooserDemo.java**:这是一个用户界面类,通常包含用于让用户选择输入和输出文件的控件。...
哈夫曼压缩是一种高效的数据压缩方法,它基于字符出现频率构建一种特殊的二叉树——哈夫曼树。在计算机科学中,尤其是信息处理和文件压缩领域,哈夫曼编码是广泛应用的技术之一。ASC II码是计算机中用8位二进制数...
总结来说,哈夫曼树压缩算法利用了数据的统计特性,通过构建最优二叉树实现高效的数据编码,进而完成数据的压缩。在实际应用中,这种算法广泛应用于文本、图像和音频等数据的压缩,提高了存储和传输的效率。
在C语言中实现哈夫曼编码的压缩与解压缩,涉及到的主要知识点包括以下几个方面: 1. **哈夫曼树的构建**:哈夫曼树是一种带权路径长度最短的二叉树。构建过程通常采用贪心策略,通过合并频率最小的两个节点来逐步...
在"哈夫曼压缩算法.cpp"这个源代码文件中,可能会包含以下部分: 1. **字符频率统计**:程序会遍历输入文件,计算每个字符的出现频率,通常使用一个字典或哈希表来存储这些信息。 2. **哈夫曼树构建**:利用频率...