- 浏览: 20636 次
- 性别:
- 来自: 长沙
最新评论
本节主要是利用huffman树的原理来对文件进行处理,从而达到压缩文件的效果。huffman树又称为最优二叉树。是带权路径最短的树。
先说说怎么建huffman树,其构造方法为:
1.根据给定的n个权值的结点,选出两个结点值最小的数作为左、右子树,这个二叉树的根结点为左、右结点的权值之和。
2.将新的权值加入到剩余结点中,删除原来的两个结点
3.重复1 2,直到最后只有一个结点为止。
Huffman压缩是一个无损的压缩算法。通过构建huffman树,可以得到每个叶结点的huffman编码,然后把源文件的字节用huffman编码来存储,从而达到减小空间占用,实现压缩。
要实现文件的压缩,可以分为如下几步:
一、根据传入的文件,统计每个字节出现的次数
二、根据每个字节出现的次数,构建一棵huffman树
三、根据huffman树,得到每个字节的huffman编码
四、把源文件和huffman编码写入文件中去
通过这几步就基本上可以实现文件的压缩。
第一步:
第二步: 第三步: 第四步:是最重要的一步,也是最关键的一步: 然后根据源文件的路径,调用方法,并制定生成的文件路径及文件名,这样就可以进行文件压缩啦。但这只是简单的压缩,可能对一些小文件进行压缩时,压缩的文件比源文件可能还大,这样还不如不压缩,这里可能还存在一些小问题,希望牛人指出。 /**
* 根据传入的文件,统计每个字节出现的次数
* @param path 文件的路径
* @return int数组
*/
public int[] fileByteCount(String path){
//存储文件中每个字节出现的次数
try{
FileInputStream fis=new FileInputStream(path);
BufferedInputStream bis=new BufferedInputStream(fis);
while(fis.available()>0){
//文件是否读完
int i=fis.read();
byteCount[i]++; //用数组存储每个字节出现的次数
}
fis.close();
bis.close();
}catch(Exception ef){
ef.printStackTrace();
}
return byteCount;
}
/**
* 创建最优二叉树的方法
* @param arr:传入的数组
* @param TreeNode:返回根结点
*/
public TreeNode createHuffman(int[] arr){
//实例化一个优先队列对象
PriorityQueue<TreeNode> queue = new PriorityQueue<TreeNode>(11,new MyComparator());
TreeNode root=null;
//遍历数组,将数组元素构建成结点,并添加到队列中
for (int i=0;i<arr.length;i++){
if(arr[i]!=0){
//创建结点,结点值不为0
TreeNode node = new TreeNode(i,arr[i]);
//将结点添加到队列中
queue.add(node);
}
}
//遍历队列,每次取出两个最小元素作为叶子结点,它们的和作为父结点建立二叉树,
//并从队列中删除这两个元素,同时把它们的父结点添加到队列中
while(queue.size()>1){
//同时取两个最小元素
TreeNode node1 = queue.poll();
TreeNode node2 = queue.poll();
//根据取得的元素创建父结点
TreeNode fnode = new TreeNode(0,node1.getZijie()+node2.getZijie());
//建立引用关系
fnode.setLeft(node1);
fnode.setRight(node2);
node1.setParent(fnode);
node2.setParent(node2);
//将父结点添加到队列中
queue.add(fnode);
}
root =queue.peek();
return root;
}
/**
* 根据根结点创建哈夫曼编码
* 规则:左子结点为:1,右子结点为:0
* @param root:根结点
*/
public void createCode(TreeNode root,String code){
//首先是确定各结点的路径
//得到子结点
TreeNode left = root.getLeft();
TreeNode right = root.getRight();
//打印叶子节点
if (left==null&&right==null){
System.out.println(root.getObj()+"的编码为:"+code);
//byteCode 的下标是字节,值为其哈夫曼编码
byteCode[(Integer)root.getObj()]=code;
}
if (left!=null){
//递归
createCode(left,code+"0");
}
if (right!=null){
//递归
createCode(right,code+"1");
}
}
/**
* 把源文件和huffman编码写入文件中去
* @param path 源文件路径
* @param path1 要写入的文件路径
* @param str huffman编码的String数组
*/
public void writeToFile(String path,String path1,String []str){
try{
FileOutputStream fos = new FileOutputStream(path1);
DataOutputStream Dos = new DataOutputStream(fos);// 创建输出流
for (int k = 0; k< str.length; k++) {
if (str[k] != null){
Dos.writeInt(k);
Dos.writeInt(str[k].length());
}else{
str[k]="";
Dos.writeInt(k);
Dos.writeInt(0);
}
}
//先把编码写入文件
int count=0;//记录中转的字符个数
int i=0;//第i个字节
String writes="";
String tranString ="";
String waiteString ;
while(i<256||count>=8){
//等待的字符大于8
if(count>=8){
waiteString="";
//讲writes前8位取出
for (int t = 0; t < 8; t++) {
waiteString = waiteString + writes.charAt(t);
}
// 将writes前八位去掉
if (writes.length() > 8) {
tranString = "";
for (int t = 8; t < writes.length(); t++) {
tranString = tranString + writes.charAt(t);
}
writes = "";
writes = tranString;
}else {
//刚好只有8位
writes = "";
}
count = count - 8;// 写出一个8位的字节
int intw = changeString(waiteString);// 得到String转化为int
// 写入文件
Dos.writeInt(intw);
}else if(count<8){
// 得到第i个编码信息等待写入
if (str[i]!= null ) {
count = count + str[i].length();
if(str[i].length()!=0){
}
writes = writes + str[i];
i++;
}
}
}
// 把所有编码没有足够8的整数倍的String补0使得足够8的整数倍,在写入
if (count > 0&&count<8) {
waiteString = "";// 清空要转化的编码
int buzero=0;
for (int t = 0; t < 8; t++) {
if (t < writes.length()) {
waiteString = waiteString + writes.charAt(t);
} else {
waiteString = waiteString + "0";
//补了多少个0
buzero++;
}
}
Dos.writeInt(changeString(waiteString));
Dos.writeInt(buzero);
}
try{
// 将源文件中的所有byte转化为01字符串,写入压缩文件
FileInputStream fis = new FileInputStream(path);
BufferedInputStream bis = new BufferedInputStream(fis);
count =0;
writes="";
tranString ="";
int idata=bis.read();
while(bis.available()>0||count>=8){
//如果缓冲区等待写入的字符超过8
if(count>=8){
waiteString="";
for (int t = 0; t < 8; t++) {
waiteString = waiteString + writes.charAt(t);
}
// 将前八位删掉
if (writes.length() > 8) {
tranString = "";
for (int t = 8; t < writes.length(); t++) {
tranString = tranString + writes.charAt(t);
}
writes = "";
writes = tranString;
} else {
writes = "";
}
count = count - 8;// 写出一个8位的字节
int intw = changeString(waiteString);
Dos.writeInt(intw);
}else {
// 如果不够8位,就继续取下一个字节
count = count + str[idata].length();
writes = writes + str[idata];
idata = bis.read();
}
}
count = count + str[idata].length();
writes = writes + str[idata];
// 把count剩下的写入
int endsint = 0;
if (count > 0) {
waiteString = "";// 清空要转化的码
for (int t = 0; t < 8; t++) {
if (t < writes.length()) {
waiteString = waiteString + writes.charAt(endsint);
} else {
waiteString = waiteString + '0';
endsint++;
}
}
Dos.writeInt(changeString(waiteString));// 写入所补的0;
Dos.writeInt(endsint);
System.out.println(endsint);
Dos.flush();
}
fis.close();
bis.close();
fos.close();
Dos.close();
}catch(Exception ef){
ef.printStackTrace();
}
}catch(Exception ef){
ef.printStackTrace();
}
}
<!--EndFragment-->
发表评论
-
深入理解HashMap(一)
2011-11-24 02:09 793以前学习HahsMap都是粗略的了解一下,能够用就行了。这次对 ... -
数组转换成二叉树
2011-08-15 01:20 2689前面介绍了双向链表,其实二叉树也相当于一个链表。二叉树相对而言 ... -
Java双向链表的实现
2011-08-10 00:06 2624学过数据结构的应该对双向链表比较熟悉,但如果用java语言是怎 ... -
多线程02
2011-08-03 00:17 671前面一节我们是通过继承Thread这个类来实现多线程,而如 ... -
多线程01
2011-08-02 00:08 581Java是支持多线程的语言,要想了解线程,我们得先知道进程。所 ... -
"= =" 和equals()的区别
2011-07-29 01:02 716在Java程序中,要比较两个对象是否相等,经常会使用到“= = ... -
"= =" 和equals()的区别
2011-07-29 01:00 0在Java程序中,要比较两个对象是否相等,经常会使用到“= = ... -
文件操作
2011-07-27 02:50 612一、File类 在整个io包中,唯一与文件本身有关的 ... -
异常的捕获与处理
2011-07-26 21:25 691在我们编写java程序时,我们经常遇到的问题就是:程序老出现问 ... -
递归算法
2011-07-26 00:27 759递归算法是一种特殊的调用形式,是方法自己调用自己,这样有点 ... -
小议Java关键字
2011-07-23 20:50 654在Java的学习过程中,我 ... -
Java中的数据结构
2011-07-05 22:20 781Java中的数据结构其实 ... -
类和对象总结
2011-05-12 19:40 608现在我们已经对java有一定的了解了,它是一个面向对象的 ... -
java入门知识小总结
2011-05-12 19:37 457谈到java,我们都知道其有一个面向对象的编程语言。在所有的编 ...
相关推荐
数据结构课程设计用哈夫曼编码实现文件压缩: 一、实验题目: 用哈夫曼编码实现文件压缩 二、实验目的: 1、了解文件的概念。 2、掌握线性链表的插入、删除等算法。 3、掌握Huffman树的概念及构造方法。 4、掌握...
C# 文件压缩-指定文件压缩
1. 分析给出的多文件打包/解包程序MyZip和单文件压缩程序Compress,将程序MyZip改写为一个能够处理多文件压缩/解压的控制台程序,可利用命令行参数控制其完成如下功能: 1. 将命令行参数指定的一组文件压缩为一个...
如果服务器上安装了RAR程序,那么asp.net可以调用RAR实现文件压缩与解压缩。 不过要注意的是,由于Web程序不能直接调用客户端的程序(除非用ActiveX,ActiveX几乎被废弃),所以如果要想实现让用户把本地文件用网页...
1G的文件压缩成1M的方法1G的文件压缩成1M的方法.rar1G的文件压缩成1M的方法.rar1G的文件压缩成1M的方法.rar1G的文件压缩成1M的方法.rar1G的文件压缩成1M的方法.rar1G的文件压缩成1M的方法.rar1G的文件压缩成1M的方法...
JAVA文件压缩与解压缩实践(源代码+论文),详细文档分析!
1G的文件压缩成1M的方法,很多网上下载的文件只有300MB或400MB,但是解压后,居然可以达到2GB甚至更多,也许你会奇怪,为什么你用WinRAR压缩同样的文件,就没有这样的压缩效果呢?其实这是因为这些文件是用多款不同...
适合练手、课程设计、毕业设计的Java项目源码:文件压缩与解压缩实践(源代码+论文).rar 适合练手、课程设计、毕业设计的Java项目源码:文件压缩与解压缩实践(源代码+论文).rar 适合练手、课程设计、毕业设计的Java...
JAVA文件压缩与解压缩实践报告 主函数 gzip压缩模块代码 压缩模块要完成的就是将文件读入以后进行压缩,再将压缩后的数据写入一个新的文件,其部分代码如下: public class gzip { public static void main(String...
Java把文件压缩成zip,粘贴在项目中即可使用
C++利用Zlib库实现zip文件压缩及解压 支持递归压缩.可配合自动更新功能实现zip压缩包进得软件更新
利用哈夫曼编码思想,设计对一个文本文件(.txt)中的字符进行哈夫曼编码,生成编码压缩文件(.txt),并且还可将压缩后的文件进行解码还原为原始文本文件(.txt)。 实现的功能: (1)压缩:实现对文件的压缩,生成...
教你如何将1G文件压缩成1M 实用啊
c语言实现文件压缩,用huffman编码实现。并修改注册表实现鼠标右击出现如同rar的简单操作。
C# rar 文件压缩 .net 压缩文件 RAR
利用C#实现文件压缩 并生成文件的xml文档说明
java实现多个文件压缩
太好用的图形文件压缩软件,它可以满足文件尺寸大小不变可文件体积大幅减小。而清晰度几乎不变。
哈夫曼编码是一种常用的数据压缩技术,对数据文件进行哈夫曼编码可大大缩短文件的传输长度,提高信道利用率及传输效率。要求采用哈夫曼编码原理,统计文本文件中字符出现的词频,以词频作为权值,对文件进行哈夫曼...