`
qq_24665727
  • 浏览: 121284 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论
阅读更多
//这是我一个学长的,我看了好久才明白,给大家分享,这里的代码只是一个压缩方法的,还有
//一些类已经上传(测试类,结构类都在文件里面),需要可以下载,这个算法没有用递归遍历整个文件夹,所以之只能压缩
//一个文件,下面是主要压缩步骤:
//整个压缩文件的内容:(写入顺序)
 * 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("完成!!");
	}

 

0
0
分享到:
评论

相关推荐

    哈弗曼编码实现压缩解压

    哈弗曼编码是一种高效的数据编码方法,常用于数据...在C++中实现哈弗曼编码与解压,需要理解哈弗曼树的构建过程,并能有效地进行编码和解码操作。通过这种技术,我们可以有效地减小文件的大小,提高存储和传输效率。

    哈弗曼树算法压缩/解压文件(Huffman)

    哈弗曼树(Huffman Tree),也称为最优二叉树,是一种特殊的二叉树结构,广泛应用于数据编码,特别...理解并掌握哈弗曼树算法对于理解和优化数据压缩过程至关重要,也是计算机科学中数据结构和算法学习的重要组成部分。

    哈弗曼算法压缩文件

    哈弗曼算法实现文件的压缩与解压算法,站在字节的高度对文件实现操作,文件压缩无损伤。

    哈弗曼的压缩和解压

    哈弗曼编码是一种高效的数据压缩算法,由美国计算机科学家戴维·哈弗曼在1952年提出。它的核心思想是构建一棵特殊的二叉树——...同时,理解哈弗曼编码的原理和实现方式对于深入学习数据压缩和信息理论具有重要意义。

    哈弗曼简单实现压缩

    哈弗曼编码(Huffman Coding)是一种数据压缩算法,由美国计算机科学家大卫·哈弗曼在1952年提出。它的主要原理是利用字符出现频率构建最优的二叉树,进而实现对数据的高效压缩。哈弗曼编码在文本、图像、音频等多种...

    哈弗曼编码 压缩 解压 文件

    本项目是针对数据结构实习编写的,目的是让学生理解并实现哈弗曼编码的压缩与解压过程。 首先,我们要了解哈弗曼树的构造过程。哈弗曼树是一种特殊的二叉树,也被称为最优二叉树。它的特点是所有叶子节点都是原始...

    C语言实现哈夫曼编码压缩和解压各种文件

    (2) 采用哈弗曼算法对各字节进行编码,建立哈弗曼对照表; a) 构造二叉树 b) 编码 (3) 依次读取原始文件的每个字节,查找其对应的哈弗曼编码,将这些位写入到压缩文件中(注意:要凑够8位二进制才写入到文件中)...

    哈弗曼压缩解压算法代码.rar

    在实际应用中,哈弗曼编码通常与其他压缩技术结合使用,如在ZIP和GZIP等压缩格式中,哈弗曼编码是作为LZ77或LZ78等滑动窗口压缩算法的后续步骤,以进一步提升压缩率。 从提供的压缩文件"201121421219072"中,我们...

    基于哈弗曼编码的数据压缩解压程序论文

    这篇基于哈弗曼编码的数据压缩解压程序论文深入探讨了如何将理论知识应用于实际编程,旨在让学生将计算机科学与技术,特别是C++编程技能,与数据结构和程序控制结构相结合。 1.1 课程设计目的 该课程设计的目标是让...

    用哈弗曼编码对文件进行压缩与解压

    ### 哈弗曼编码对文件进行压缩与解压 #### 概述 哈弗曼编码(Huffman Coding)是一种广泛应用于数据压缩领域的算法。...此外,通过计算压缩速度、解压速度和压缩率等指标,还可以对压缩算法的性能进行定量评估。

    哈弗曼压缩解压算法VC++源码示例

    哈弗曼编码(Huffman Coding)是一种数据压缩算法,由美国计算机科学家大卫·艾尔曼在1952年提出。...在实际项目中,哈弗曼压缩算法常用于文本、图像和其他类型数据的压缩,以节省存储空间和提高传输效率。

    哈弗曼树的文件压缩和解压实验报告C语言.docx

    《哈弗曼树在文件压缩与解压中的应用——C语言实现》 哈弗曼树,又称为最优二叉树,...实验报告不仅提供了具体的代码实现,还包含了对算法性能的分析,对于理解和掌握哈弗曼编码及其在文件压缩中的应用具有重要意义。

    哈弗曼树的文件压缩和解压实验报告(C语言源代码)

    ### 哈弗曼树的文件压缩和解压实验报告 #### 1. 哈弗曼树简介 哈弗曼树(Huffman Tree),又称最优二叉树,是一种带权路径长度最短的二叉树,即在二叉树中任何一个叶子节点的权值均大于其父节点。哈弗曼树广泛应用...

    哈弗曼压缩解压算法,VC 源代码下载.rar

    在VC(Visual C++)环境中实现哈弗曼压缩和解压,通常涉及到以下几个关键步骤: 1. **频率统计**:首先,我们需要对输入的数据流进行分析,统计每个字符出现的频率。这是构建哈弗曼树的基础。 2. **构建哈弗曼树**...

    哈弗曼树进行压缩编码

    在信息编码中,哈弗曼编码是一种可变长度的前缀编码方式,它根据字符出现频率构建哈弗曼树,使得出现频率高的字符具有较短的编码,而出现频率低的字符编码较长,从而实现高效的数据压缩。 哈弗曼编码的过程主要包括...

    哈弗曼压缩解压器.rar

    哈弗曼编码是一种高效的数据压缩方法,由美国计算机科学家戴维·艾伦·哈弗曼在1952年提出...在使用“哈弗曼压缩解压器”这样的工具时,确保正确处理每个字符,特别是像空白字符这样的细节,是获得良好压缩效果的关键。

    哈弗曼算法程序(C)

    在C语言中实现哈弗曼算法通常包括以下几个步骤: 1. **字符频率统计**:首先,我们需要统计输入文本中每个字符出现的次数,这可以使用数组或者哈希表来完成。在C程序中,可以定义一个字符数组和对应的整型数组,...

    哈弗曼压缩和解压以及多项式的运算

    在本文件中,结合了哈弗曼编码和多项式运算,可能是实现了一个能够处理这两种操作的程序。使用MFC(Microsoft Foundation Classes)作为界面框架,可以创建用户友好的图形界面,使得用户能够方便地输入数据,执行...

    利用哈弗曼编码做的压缩程序 源代码

    哈弗曼编码是一种高效的数据压缩方法,源自于1952年由David A. Huffman提出,因此得名。...虽然本压缩程序的压缩比可能并不高,但它的算法设计和实现技巧仍然具有学习价值,可以帮助理解数据压缩的基本原理和方法。

Global site tag (gtag.js) - Google Analytics