`
jcs130
  • 浏览: 131183 次
  • 性别: Icon_minigender_1
  • 来自: Ottawa
社区版块
存档分类
最新评论

菜鸟说:哈夫曼压缩的解压缩~~(附源代码)

阅读更多

解压就是压缩的逆过程……真是说起来容易做起来难啊……

 

不过最后还是做出来了,而且发现了前面的压缩函数的几个问题:

 

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
1
4
分享到:
评论

相关推荐

    哈夫曼实现压缩解压缩——源代码

    在"哈夫曼实现压缩解压缩——源代码"中,我们可以期待看到一个用C语言在Linux环境下实现的哈夫曼编码和解码过程。 哈夫曼编码的过程主要包括以下步骤: 1. **构建哈夫曼树**:首先,统计所有字符的出现频率,创建...

    哈夫曼压缩与解压缩源码.zip

    哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩源码.zip哈夫曼压缩与解压缩...

    哈夫曼压缩解压缩

    总之,哈夫曼压缩解压缩是数据压缩领域的一个重要方法,通过MFC和VC++,我们可以构建出直观且高效的压缩工具,便于学习和研究。在这个过程中,理解哈夫曼编码的原理、掌握MFC的使用以及实现压缩和解压缩的算法,都是...

    运用哈夫曼编码压缩解压文件源代码

    哈夫曼编码压缩解压文件源代码 哈夫曼编码是一种变长前缀编码方案,用于压缩数据。哈夫曼树是一种特殊的二叉树,它的每个叶子结点对应一个字符,而每个内部结点对应一个符号的频率信息。哈夫曼编码的基本思想是:将...

    哈夫曼压缩解压缩的代码

    总的来说,哈夫曼压缩解压缩的Java代码涉及到了数据结构(二叉树、优先队列)、编码理论、文件I/O以及错误处理等多个方面的知识。理解和实现这一过程有助于深入理解数据压缩原理,提高编程能力。

    哈夫曼编码实现压缩解压缩java

    哈夫曼编码是一种高效的数据编码方法,主要用于无损数据压缩,尤其在文本文件的压缩中表现出色。这种编码方式基于频率最小的字符用最短的二进制代码表示的原理,能够有效地减少数据存储和传输时的位数,从而达到压缩...

    哈夫曼解压缩程序

    哈夫曼解压缩程序,通常被称为Szip,是一种基于哈夫曼编码的高效数据压缩算法。在信息技术领域,数据压缩是存储和传输信息的关键技术,它通过减少数据冗余来节省存储空间和提高传输效率。哈夫曼编码是数据压缩中的...

    哈夫曼编码压缩解压缩程序(CPP写的)

    《哈夫曼编码压缩解压缩程序的实现及原理》 哈夫曼编码是一种高效的数据压缩方法,它基于字符出现频率构建最优的二叉树结构,从而实现数据的压缩与解压缩。本文将深入探讨哈夫曼编码的原理,并通过一个使用C++编写...

    哈夫曼压缩解压算法-C语言

    mypage文件可能包含了实现哈夫曼压缩和解压缩算法的C源代码文件,以及相关的测试数据或结果。通过阅读和理解这些代码,你可以深入学习哈夫曼编码的工作原理,以及如何在C语言中实现这一算法。同时,还可以了解到如何...

    哈夫曼压缩程序源代码

    文件列表中的`huffman.c`是源代码文件,包含了哈夫曼压缩和解压缩算法的实现,而`huffman.exe`是编译后的可执行文件,可以直接运行进行压缩和解压缩操作。在实际使用中,用户可能需要提供待压缩的文件作为输入,然后...

    利用哈夫曼原理的压缩解压缩软件

    总的来说,这款“利用哈夫曼原理的压缩解压缩软件”结合了哈夫曼编码的高效压缩算法和MFC的用户界面设计,为用户提供了一种便捷且直观的文件压缩和解压缩工具。其核心在于哈夫曼编码的优化和MFC的UI实现,确保了压缩...

    哈夫曼压缩与解压缩

    哈夫曼实现文件的压缩与解压缩,代码关键部分有注释。

    哈夫曼压缩——GUI

    这个项目“哈夫曼压缩——GUI”是基于Visual Studio 2010开发的一个图形化界面工具,对于学习数据结构和算法的学生来说,是一个很好的实践案例。 1. **哈夫曼编码**:哈夫曼编码是一种变长的前缀编码方式,通过构建...

    哈夫曼压缩源代码

    通过阅读和理解这些源代码,你可以更深入地了解哈夫曼压缩的具体实现细节,包括如何构建和操作哈夫曼树,以及如何有效地进行编码和解码操作。学习这部分内容对于理解和实现数据压缩算法,优化文件存储和传输效率具有...

    C++课程设计:哈夫曼算法的文件压缩程序

    4. **文件解压缩**:在解压时,根据编码表重建哈夫曼树,然后读取编码流,根据编码恢复原始字符,从而完成解压缩过程。 在C++中实现这个程序,你需要理解并运用以下知识点: - **文件操作**:包括读取文件内容、...

    哈夫曼树压缩解压C++代码

    `SRC`文件可能包含了C++源代码,展示如何构建哈夫曼树、生成编码、压缩和解压数据的具体实现。`DOC`文件可能是实验报告,详细解释了这些过程并分析了算法的效率。`EXE`文件则可能是编译后的可执行程序,可以直接运行...

    哈夫曼压缩与解压缩程序(JAVA)

    在Java编程环境中实现哈夫曼压缩与解压缩程序,我们可以利用面向对象的特性,设计多个类来完成不同部分的功能。 1. **FileChooserDemo.java**:这是一个用户界面类,通常包含用于让用户选择输入和输出文件的控件。...

    哈夫曼压缩与解压缩设计

    哈夫曼压缩是一种高效的数据压缩方法,它基于字符出现频率构建一种特殊的二叉树——哈夫曼树。在计算机科学中,尤其是信息处理和文件压缩领域,哈夫曼编码是广泛应用的技术之一。ASC II码是计算机中用8位二进制数...

    哈夫曼树压缩算法实现

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

    哈夫曼压缩算法(源代码+实现报告)

    在"哈夫曼压缩算法.cpp"这个源代码文件中,可能会包含以下部分: 1. **字符频率统计**:程序会遍历输入文件,计算每个字符的出现频率,通常使用一个字典或哈希表来存储这些信息。 2. **哈夫曼树构建**:利用频率...

Global site tag (gtag.js) - Google Analytics