经过几天的努力终于把霍夫曼压缩弄好了,其中几经波折,2度误删,幸好每一天的备份都在,并不是重头再来。
霍夫曼压缩是根据霍夫曼编码,将源文件中的字节编码重组的压缩。即将所有字节通过霍夫曼树转化为01串,由于霍夫曼树的特性,频数多的字节必定只有很短的霍夫曼编码,所以文件得以压缩。它的压缩效率主要在于你的压缩信息文件的大小和文件自身。
霍夫曼压缩基于前篇文章的二叉树类编写,故部分代码略去。
根据映射建立霍夫曼树的方法
public void creatHuffmanTree(HashMap<Byte,Integer> hmap) {
if (hmap.isEmpty()) {
throw new RuntimeException("空映射,无法建树");
} else {
// 得到K的Set集合
java.util.Set<Byte> set = hmap.keySet();
int len = set.size();
int arr[] = new int[len];
byte mem[] = new byte[len];
// 遍历K的集合,得到set的迭代器
java.util.Iterator<Byte> iter = set.iterator();
int i=0;
while (iter.hasNext()) {
// 取出一个key
byte num = iter.next();
// 根据key得到对应的Value
int name = hmap.get(num);
mem[i] = num;
arr[i] = name;
i++;
// System.out.println(num + "\t" + name);
}
// 创建优先队列对象
PriorityQueue<TNode> que = new PriorityQueue<TNode>(arr.length,
new MyComparator());
// 将数组中的元素建立结点对象并加入到优先队列中去
for (int j = 0; j < arr.length; j++) {
TNode node = new TNode(arr[j]);
node.setByt(mem[j]);
que.add(node);
}
System.out.println("size="+que.size());
while (que.size() > 1) {
// 将两个结点连成树
TNode ltree = que.poll();
TNode rtree = que.poll();
TNode node = new TNode((Integer) ltree.getObj()
+ (Integer) rtree.getObj());
node.setLeft(ltree);
node.setRight(rtree);
ltree.setParent(node);
rtree.setParent(node);
// 加入子结点
que.add(node);
}
root = que.poll();
}
}
计算文件中字节出现的频数,便于建立霍夫曼树
public int count(String path) {
java.io.File file = new java.io.File(path);
boolean b = file.isDirectory();
if (b) {
System.out.println("错误!给予的路径为文件夹");
return 0;
}
Boolean b1 = file.exists();
if (!b1) {
System.out.println("错误!给予的路径不存在");
return 0;
}
try {
// 根据原始文件路径创建文件输入流对象
java.io.FileInputStream fis = new java.io.FileInputStream(path);
java.io.BufferedInputStream bis = new java.io.BufferedInputStream(fis);
// 从fis中读取一个字节
int data = bis.read();
byte dat = (byte)data;
while (data != -1) {
if (amap.get(dat) == null) {
amap.put( (byte)data, 1);
} else {
amap.put( (byte)data, amap.get(dat) + 1);
}
data =bis.read();
dat = (byte)data;
}
// 关闭输出与输入流
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
return 1;
}
读取目标文件并转换成霍夫曼编码的方法
public void readfile(String path, HashMap<Byte, String> hcmap) {
// 根据原始文件路径创建文件输入流对象
try {
java.io.FileInputStream fis = new java.io.FileInputStream(path);
java.io.BufferedInputStream bis = new java.io.BufferedInputStream(
fis);
// 从fis中读取一个字节
int data = bis.read();
byte dat = (byte) data;
while (data != -1) {
if (code == null) {
code = hcmap.get(dat);
// System.out.println("first "+code);
// System.out.println();
} else {
// System.out.println();
// System.out.println(dat + " " + hcmap.get(dat));
code = code.concat(hcmap.get(dat));
// System.out.println("concat "+hcmap.get(dat));
}
data = bis.read();
dat = (byte) data;
}
// 关闭输出与输入流
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
将压缩后的数据与压缩信息写入文件中的方法
public void Outtofile(String path, HashMap<Byte, String> hcmap) {
try {
// 建立输出流对象
java.io.FileOutputStream fos = new java.io.FileOutputStream(path);
DataOutputStream bos = new java.io.DataOutputStream(fos);
// 将字符串的装换规则写入文件的开头
// 得到K的Set集合
java.util.Set<Byte> set = hcmap.keySet();
// 先写入拥有的转换规则的个数
int len = set.size();
System.out.println("len1= " + len);
bos.writeInt(len);
// 遍历K的集合,得到set的迭代器
java.util.Iterator<Byte> iter = set.iterator();
while (iter.hasNext()) {
// 取出一个key
byte key = iter.next();
int resu;
// 根据key得到对应的Value
String result = hcmap.get(key);
// if (result.length() <= 8) {
bos.writeByte(key);
int b = result.length();
BigInteger bi = new BigInteger(result, 2);
String res = bi.toString(10);
resu = Integer.valueOf(res);
bos.writeInt(b);
bos.writeInt(resu);
}
// 数据的长度
int length;
if (code.length() % 8 == 0) {
length = code.length() / 8;
} else {
length = code.length() / 8 + 1;
}
// 将长度写入文件中
bos.writeInt(length);
BigInteger value;
// 将01字符串转换为字节写入文件中
while (!code.isEmpty()) {
// 如果字符串大于8,则将前8个写入,并将前面的截去
if (code.length() >= 8) {
String s = code.substring(0, 8);
value = new BigInteger(s, 2);
String r = value.toString(10);
int j = Integer.valueOf(r);
bos.write(j);
code = code.substring(8);
} else {// 如果字符串小于8,则将前n个读取,并在后面补0补足8个,然后写入
String s = code.substring(0, code.length());
int time = 0;
while (s.length() != 8) {
s = s.concat("0");
time++;
}
value = new BigInteger(s, 2);
String r = value.toString(10);
int j = Integer.valueOf(r);
bos.write(j);
bos.writeInt(time);
code = "";
}
}
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
解压缩的方法
public int anticomp(String opath, String path) {
// 判断给予的元素文件路径是否是文件夹,是否存在
java.io.File file = new java.io.File(opath);
boolean b = file.isDirectory();
if (b) {
System.out.println("错误!给予的路径为文件夹");
return 0;
}
Boolean b1 = file.exists();
if (!b1) {
System.out.println("错误!给予的路径不存在");
return 0;
}
try {
// 根据原始文件路径创建输入流对象
java.io.FileInputStream fis = new java.io.FileInputStream(opath);
java.io.DataInputStream bis = new java.io.DataInputStream(fis);
// 根据目标文件路径创建输出流对象
java.io.FileOutputStream fos = new java.io.FileOutputStream(path);
java.io.DataOutputStream bos = new java.io.DataOutputStream(fos);
// 创建映射用于解码
HashMap<String, Byte> hmap = new HashMap<String, Byte>();
// 读取长度
int len = 0;
len = bis.readInt();
System.out.println("len2= " + len);
String value;
//读取映射的信息
while (len != 0) {
byte key = bis.readByte();
int num = bis.readInt();
int v = bis.readInt();
value = Integer.toBinaryString(v);
while (num > value.length()) {
value = "0" + value;
}
hmap.put(value, key);
len--;
}
// 得到K的Set集合
java.util.Set<String> set = hmap.keySet();
// 遍历K的集合,得到set的迭代器
java.util.Iterator<String> iter = set.iterator();
while (iter.hasNext()) {
// 取出一个key
String num = iter.next();
// 根据key得到对应的Value
byte name = hmap.get(num);
}
System.out.println("size=" + set.size());
// 开始解码
String data = "";
int length = bis.readInt();
//用byte数组接受数据
byte arr[] = new byte[length + 1];
bis.read(arr);
//将数组所有数据全部转化为string加到data上
for (int k = 0; k < length; k++) {
int result = arr[k] & 0xff;
String wdata = Integer.toBinaryString(result);
while (wdata.length() < 8) {
wdata = "0" + wdata;
}
data = data + wdata;
}
System.out.println(" data = " + data.substring(0, 8));
System.out.println(" data = " + data.substring(8, 16));
int time = arr[length] & 0xff;
data = data.substring(0, data.length() - time);
int flag = 1;
String s = data.substring(0, flag);
//通过建立的映射解码
while (data.length() != 0) {
if (hmap.get(s) == null) {
flag++;
if (data.length() != 0) {
s = data.substring(0, flag);
}
} else {
bos.write(hmap.get(s));
data = data.substring(flag, data.length());
flag = 1;
if (data.length() != 0) {
s = data.substring(0, flag);
}
}
}
// 刷新此输出流并强制写出所有缓冲的输出字节
fos.flush();
// 关闭输出与输入流
fis.close();
fos.close();
hmap.clear();
} catch (Exception e) {
e.printStackTrace();
}
return 1;
}
}
因为很多信息文件都是使用int类型写入的,所以压缩效率貌似一般
解压完成
- 大小: 12.9 KB
- 大小: 120 KB
分享到:
相关推荐
通过以上步骤,我们可以编写一个C程序,实现霍夫曼压缩和解压缩。该程序的压缩部分将文本文件转换为霍夫曼编码的二进制格式,而解压缩部分则读取这个二进制文件,使用预先构建的霍夫曼树将编码还原为原始文本。在这...
基于霍夫曼编码、费诺编码、霍夫曼压缩、LZ77压缩C仿真源码.zip 代码完整下载可用,确保可以运行。 基于霍夫曼编码、费诺编码、霍夫曼压缩、LZ77压缩C仿真源码.zip 代码完整下载可用,确保可以运行。基于霍夫曼...
压缩包中的`霍夫曼压缩解压缩`可能包含了这两个函数的源代码,以及其他辅助函数或测试用例。通过阅读和理解这些代码,我们可以深入了解霍夫曼编码在MATLAB中的实现细节,并且能够根据需求调整和扩展功能。 总结来说...
《霍夫曼压缩编码在MFC中的实现》 霍夫曼压缩编码,也称为霍夫曼编码,是一种基于字符频率的变长编码方法,广泛应用于数据压缩领域。它通过为频繁出现的字符分配较短的编码,而为不常见的字符分配较长的编码,从而...
在Visual C++ 6.0环境下,开发霍夫曼压缩解压程序主要涉及以下几个关键步骤: 1. **构建霍夫曼树**:首先,需要统计输入文本中各个字符的出现频率。然后,根据这些频率创建一个优先队列(通常使用二叉堆实现),并...
参加了编程大赛,实现对文件的压缩,本人选择了java实现。 通过大量的知识资源搜索...Hfm(霍夫曼压缩算法) 0.7309 0.5672 0.7233 LZ77(滑动窗口算法) 4.091 2.5476 2.9278 LZAM(数据压缩算法) 0.573 0.285 0.319
数据结构中的霍夫曼压缩(Huffman Coding)是一种高效的无损数据压缩算法,它基于字符频率构建最优前缀编码,从而实现对数据的压缩。在本文中,我们将深入探讨霍夫曼编码的基本原理、实现步骤以及其在文件压缩过程中...
资源内容:基于霍夫曼编码、费诺编码、霍夫曼压缩、LZ77压缩C仿真(完整代码+说明文档+数据).rar 代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 适用对象:工科生、数学专业、算法等方向...
自己编的一个霍夫曼压缩txt文档源代码,提交上来望批评指正
对于几十K的文本文件,霍夫曼压缩可以显著地减少文件大小,尤其当文件包含大量重复字符时。然而,霍夫曼编码并不适用于所有情况,例如,对于已经压缩过的数据或者含有大量不常见字符的文件,可能不会有太大的压缩...
本主题聚焦于两种经典的压缩算法:香农-费诺编码(Shannon-Fano Coding)和霍夫曼编码(Huffman Coding),以及如何计算它们的压缩率。 香农-费诺编码是由信息论创始人克劳德·香农和罗伯特·费诺共同提出的无损...
java实现霍夫曼(huffman)树的压缩和解压缩,支持对文档的压缩和解压缩
霍夫曼(Huffman)编码是一种常见的无损数据压缩方法,尤其适用于具有大量重复字符的数据。本主题将深入探讨霍夫曼编码在图像压缩和重建中的应用,并结合Matlab代码进行解析。 1. 霍夫曼编码原理: 霍夫曼编码是一...
霍夫曼压缩算法,也称为霍夫曼编码,是一种数据压缩方法,由美国计算机科学家戴维·霍夫曼在1952年提出。它是基于频率的变长编码技术,适用于无损数据压缩,尤其适合于对具有大量重复字符的数据进行压缩。在本文中,...
在"霍夫曼压缩"这个文件中,可能包含了实现霍夫曼编码的源代码,以及可能的测试用例。源代码可能包括以下几个关键部分: - **频率统计**:读取原始文件,计算每个字符的出现频率。 - **构建霍夫曼树**:根据频率...
程序实现了c语言下霍夫曼文本压缩,测试的结果是:118M的文本压缩需要7s,解压需要4s。程序采用wchar读取字符,所以可以识别汉字。字符的存储采用散列,既考虑了速度,又兼顾了空间。压缩用最大堆来构造霍夫曼树。...
在图像处理和数据压缩领域,编码技术起着至关重要的作用,它可以有效地减小文件的存储空间,提高传输效率。本文将深入探讨C语言实现的三种编码算法:霍夫曼编码、香农-费诺编码以及算术编码,并结合MFC(Microsoft ...
霍夫曼编码是一种数据压缩技术,它基于字符出现频率对字符进行编码,使得频繁出现的字符拥有较短的编码,不常出现的字符则有较长的编码,从而达到高效压缩数据的目的。在图像处理领域,霍夫曼编码常用于无损压缩,...
在“hfm.rar”这个压缩包中,包含了对霍夫曼压缩解压缩算法的讨论和可能的实现。文件“www.pudn.com.txt”可能是关于该主题的文档或文章,可能详细介绍了霍夫曼编码的原理和应用。而“hfm”文件可能是一个程序或代码...