//这是我一个学长的,我看了好久才明白,给大家分享,这里的代码只是一个压缩方法的,还有 //一些类已经上传(测试类,结构类都在文件里面),需要可以下载,这个算法没有用递归遍历整个文件夹,所以之只能压缩 //一个文件,下面是主要压缩步骤: //整个压缩文件的内容:(写入顺序) * 1.将原文件大小写入文件 dos.writeInt(fileSize); * 2.将码表的大小写入文件 dos.writeInt(mapSize); * 3.将每个字节写入文件fos.write(listBy.get(i)); * 4.将每个字节对应的哈夫曼编码大小写入文件fos.write(codeSize); * 5.将每个字符对应的哈夫曼编码写入文件dos.writeChars(hfmcode_next); * 6.写入压缩后的字节数组的大小 * 7.写入文件内容 // import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.HashMap; import java.util.List; import javax.swing.tree.TreeNode; /** * 整个压缩文件的内容:(写入顺序) * 1.将原文件大小写入文件 dos.writeInt(fileSize); * 2.将码表的大小写入文件 dos.writeInt(mapSize); * 3.将每个字节写入文件fos.write(listBy.get(i)); * 4.将每个字节对应的哈夫曼编码大小写入文件fos.write(codeSize); * 5.将每个字符对应的哈夫曼编码写入文件dos.writeChars(hfmcode_next); * 6.写入压缩后的字节数组的大小 * 7.写入文件内容 * @author yan * */ public class yasu { private String hashcode_path="D:\\实验文件夹\\HashCode.txt";//存储所有字节哈弗曼编码01串 /** * 读取文件 * * @param path * :文件路径 * @return:将文件的内容以字节数组的样式返回 */ public static byte[] readFile(String path) { byte[] dataByte = null; try { java.io.FileInputStream fis = new java.io.FileInputStream(path); //int size = fis.available();// 可读的字节数 File f = new File(path); long size1=f.length();//这样子也可以获取源文件的大小,并且还很准确。 int size=(int)size1; dataByte = new byte[size]; fis.read(dataByte); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return dataByte; } /** * 将码表的相关信息写入文件 * * @param fileSize * :原文件大小 * @param map * :存放码表的map * @param listCh * :存放关键码的字符队列 * @param path * :文件路径 * @throws Exception */ public static void writeMap(int fileSize, java.util.HashMap<Byte, String> map, List<Byte> listBy, String path) throws Exception { java.io.FileOutputStream fos = new java.io.FileOutputStream(path); java.io.DataOutputStream dos = new java.io.DataOutputStream(fos); dos.writeInt(fileSize);//1. 将原文件大小写入文件 int mapSize = map.size();// 码表的大小 dos.writeInt(mapSize);// 2.将码表的大小写入文件 for (int i = 0; i < mapSize; i++) { fos.write(listBy.get(i));// 3.将每个字节写入文件 String hfmcode_next = map.get(listBy.get(i));// 得到每个字节对应的哈夫曼编码 byte codeSize = (byte) hfmcode_next.length(); fos.write(codeSize);// 4.将每个字节对应的哈夫曼编码大小写入文件 dos.writeChars(hfmcode_next);// 5.将每个字符对应的哈夫曼编码写入文件 } dos.flush(); fos.close(); } /** * 将压缩好的字节数组写入文件 * * @param b * :压缩好的字节数组 * @param path * :文件路径 */ public static void writeFile(byte[] b, String path) { try { java.io.FileOutputStream fos = new java.io.FileOutputStream(path, true); java.io.DataOutputStream dos = new java.io.DataOutputStream(fos); // 写入字节数组的大小 dos.writeInt(b.length); fos.write(b); fos.flush(); fos.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 将10字符串以8个为一组转化为一个字节数组 * * @param str * @return */ //String ->char[]->byte( char数组转换成byte数组 然后把一个8个字节大小的byte数组转换成一个2进制的值,然后强制转型为byte 实现压缩。。。结果得到一个byte类型的值)-> private byte[] StringToByteArray(String str) { char[] c = str.toCharArray();// 将字节串str转化为字符数组c int len = c.length;// 字符串字符的个数 int lenByte; String s = ""; char c_next; byte[] b;//存放已经转换成字节的01串 if (len % 8 == 0) {// 如果字符串的长度能被8整除 lenByte = len / 8 + 1;//+1是因为最后一个要存放补0的个数 b = new byte[lenByte]; for (int i = 0; i < lenByte - 1; i++) { for (int j = i * 8; j < (i + 1) * 8; j++) { c_next = c[j]; s = s + c_next;//第i个组的01串,每8个一组(分离出8个01串字符,) } //System.out.println("第" + i + "个字符串:" + s); System.out.println("进入转化8个01串的方法"); b[i] = CharArrayToByte(s);//把一组01字符串转化成一个字节 s = ""; //System.out.println("第" + i + "个字符串转化为字节后的值:" + b[i]); } b[lenByte - 1] = 0;// 字节数组的最后一个存放补0的个数 } else {// 如果字符串的长度不能被8整除 lenByte = len / 8 + 2; b = new byte[lenByte]; int remainder = len % 8;// 求出除8的余数 int zeroNum = 8 - remainder;// 补0的个数 //System.out.println("补0数:" + zeroNum); //System.out.println("原字符串:" + str); for (int i = 0; i < zeroNum; i++) { str = str + '0';// 在字符串后面补0 } //System.out.println("补0后的字符串:" + str); c = str.toCharArray(); //System.out.println("补0后的字符串的字符个数:" + c.length); for (int i = 0; i < lenByte - 1; i++) { for (int j = i * 8; j < (i + 1) * 8; j++) { c_next = c[j]; s = s + c_next; } //System.out.println("第" + i + "个字符串:" + s); b[i] = CharArrayToByte(s); s = ""; //System.out.println("第" + i + "个字符串转化为字节后的值:" + b[i]); } b[lenByte - 1] = (byte) zeroNum;// 字节数组的最后一个存放补0的个数 } return b; } /** * 将8字符串(8个字节)转化为一个字节,(其实这里便是压缩过程。。。) * 把一个8个字节大小的byte数组转换成一个2进制的值,然后强制转型为byte 实现压缩。。。 * @param str: 传入的8字符串 * * @return: 一个字节 */ private byte CharArrayToByte(String str) { char[] c = str.toCharArray();// 将字符串str转化为字符数组c int len = c.length; byte[] b = new byte[len]; byte value = 0; byte value_next; for (int i = 0; i < len; i++) { b[i] = Byte.parseByte(c[i] + "");//此方法将返回由十进制参数表示的字节值 // System.out.println(b[i]); } //把一个8个字节大小的byte数组转换成一个2进制的值,然后强制转型为byte 8位就是2的8次方,则最大为256 实现压缩。。。。。 for (int i = 0; i < len; i++) { value_next = (byte) (b[i] * Math.pow(2, len - i - 1));// 幂计算,括号里面计算一组01串的二进制数 value = (byte) (value + value_next); //b[i] * Math.pow(2, len - i - 1)这个计算的是一个没有符号位的8位01串,它的范围是0到256,但是byte是-128到127,所以会出现负值 //在解压的时候转换成int类型时候+256 } return value; } /** * 把哈弗曼编码01串存入文件 */ public static void Save_hashcode(String path,String hfmcode){ try { FileWriter fw=new FileWriter(path); BufferedWriter bw=new BufferedWriter(fw); bw.write(hfmcode); bw.flush(); fw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 压缩文件 * * @param path1 * :原文件路径 * @param path2 * :压缩后的文件路径 * @throws Exception */ public void CompressFile(String path1, String path2) throws Exception { // 从文件中得到字节数组 System.out.println("进入压缩方法"); byte[] b = yasu.readFile(path1); int b_size = b.length;// 原文件大小 byte[] b_compress;// 字节数组,存放压缩的字符串 String hfmcode = "";// 文件内所有字节的哈夫曼编码 String hfmcode_next;// 文件中每个字节的哈夫曼编码 // ********上面那么多就是想要得到码表和存放关键码队列 Tree hfm = new Tree(); HashMap<Byte, String> map = hfm.M(path1);//这个是存有byte和相应的编码的haspmap键值对 // 接下来获得存放关键码的队列(存有字节名称的list集合) List<Byte> listBy = hfm.L(path1); for (int i = 0; i < b_size; i++) { // 得到每个字节的哈夫曼编码 hfmcode_next = map.get(b[i]); // 字节b[i]对应的哈夫曼编码 // System.out.println("第" + i + "个: " + b[i] + "的编码:" + hfmcode_next); hfmcode = hfmcode + hfmcode_next;// 将每个字节的哈夫曼编码依次相加为一个01字符串 } // hfmcode存放源文件所有字节一一对应的哈夫曼编码 //System.out.println("01串大小:" + hfmcode.length()); //System.out.println("01串:" + hfmcode); char[] ch = hfmcode.toCharArray(); // 将源文件的哈夫曼编码转化成字符数组 //System.out.println("01串的大小:" + ch.length); // 将源文件的哈夫曼编码转化 得到对应的字节数组,这个方法StringToByteArray(hfmcode); //实现了将8个byte字节转换成一个2进制数然后又转换为byte,实现压缩 b_compress = StringToByteArray(hfmcode); //for (int i = 0; i < b_compress.length; i++) { //System.out.println("第" + i + "个字节" + b_compress[i]); // } System.out.println("进入写入***********"); // 1.将文件大小和码表相关信息写入文件 writeMap(b_size, map, listBy, path2); // 2.将字节数组写入文件 writeFile(b_compress, path2); Save_hashcode(hashcode_path,hfmcode); System.out.println("完成!!"); }
相关推荐
利用哈弗曼实现压缩解压,稍稍改动就能对文件进行压缩
哈弗曼树算法压缩/解压文件,文件需要在release模式下执行,可进行encode和decode设置。简单快捷,很不错的代码,多次被国外教授当做例子讲解。有任何问题可留言。
哈弗曼算法实现文件的压缩与解压算法,站在字节的高度对文件实现操作,文件压缩无损伤。
(2) 采用哈弗曼算法对各字节进行编码,建立哈弗曼对照表; a) 构造二叉树 b) 编码 (3) 依次读取原始文件的每个字节,查找其对应的哈弗曼编码,将这些位写入到压缩文件中(注意:要凑够8位二进制才写入到文件中)...
哈弗曼压缩解压算法代码
VC++基于哈弗曼算法的一个压缩和解压的VC例子,可视界面操作,可方便运用到程序里面。
C语言写的简单的哈弗曼树文件压缩与解压,实验报告格式, 内含:源代码+运行结果截图+算法描述
VC 基于哈弗曼算法的一个压缩和解压的VC例子,可视界面操作,可方便运用到程序里面。
5.郑重声明:本软件仅供学习交流之用,但下载者不要被局限于此,还应探究更好的算法和实现。更不要抄袭以应付考试等,否则后果自负! 6.体验过程中若发现问题或不足,请与我联系,我会继续优化,谢谢!
1.对txt文件压缩和解压的程序,使用动态编码。 2.使用Huffman编码压缩和解压时,Huffman树的存储可以直接存储树结构,也可以存储所有字符的频度或权值,然后读取时建立Huffman树; 3.使用Huffman编码压缩和解压时,...
用哈弗曼树的算法来对txt文件和doc文件进行压缩,并且可以解压
数据压缩的基本概念和重要性对目前主要的压缩方法作了简单的说明并给出了数据压缩过程的基本模型以Haffman编码为主要研究对象分析了实现该算法的数据结构并以一个实例说明了Haffman编码的主要过程
哈弗曼压缩和解压,都能实现,任何文件,里面是整套工程,压缩或解压时请把源文件放在代码文件夹中,目标文件也会产生在代码文件夹中
实现一种ARGB数据(二进制数据)的无损压缩/解压单元,用于GPU或其它存储器图形图像访问密集的系统中,利用无损数据压缩技术降低存储器带宽,提高访问效率。总体要求: 研究一种高效的ARGB数据压缩/解压算法; ...
实现一种ARGB数据(二进制数据)的无损压缩/解压单元,用于GPU或其它存储器图形图像访问密集的系统中,利用无损数据压缩技术降低存储器带宽,提高访问效率。总体要求: 研究一种高效的ARGB数据压缩/解压算法; ...
实现一种ARGB数据(二进制数据)的无损压缩/解压单元,用于GPU或其它存储器图形图像访问密集的系统中,利用无损数据压缩技术降低存储器带宽,提高访问效率。总体要求: 研究一种高效的ARGB数据压缩/解压算法; ...
实现哈弗曼压缩及解压缩功能,并计算压缩前后文件占用空间比 模型建立与题目分析 压缩: 以二机制可读形式打开源文件,以二进制可写形式打开压缩目标文件。每次从源文件读取八个比特(一字节),作为一个ASCII码...
4) 要求实现一个基于哈夫曼树的文件压缩程序和文件解压程序 5) 课程选作内容:显示压缩率,图形图形化窗口操作界面 A软件名称:基于哈夫曼编码的文件压缩实用程序系统 B软件组成:WinZip.exe C制作平台及相关调试...