文件压缩的原理压缩卷是什么意思?

谈谈zip的压缩原理与代码实现_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
18页免费12页1下载券21页免费28页1下载券2页1下载券4页4下载券2页免费3页1下载券2页1下载券7页免费
谈谈zip的压缩原理与代码实现|最​近​在​研​究​图​片​的​压​缩​算​法​,​发​现​J​P​G​、​G​I​F​等​都​或​多​或​少​有​失​真​。​后​来​发​现​经​过​经​过​变​换​处​理​后​,​可​以​采​用​Z​I​P​的​压​缩​算​法​来​实​现​,​于​是​深​入​学​习​研​究​了​一​下​Z​I​P​压​缩​算​法​。​对​于​Z​I​P​压​缩​算​法​,​首​先​要​搞​清​楚​他​的​原​理​,​才​方​便​编​写​代​码​去​实​现​他​。
把文档贴到Blog、BBS或个人站等:
普通尺寸(450*500pix)
较大尺寸(630*500pix)
你可能喜欢请问自解压文件的原理是什么?
[问题点数:100分,结帖人xhh_88]
请问自解压文件的原理是什么?
[问题点数:100分,结帖人xhh_88]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
相关帖子推荐:
2002年7月 总版技术专家分月排行榜第二
2002年7月 Delphi大版内专家分月排行榜第一2002年6月 Delphi大版内专家分月排行榜第一
本帖子已过去太久远了,不再提供回复功能。GIP是什么?
GIP是什么?
09-03-03 & 发布
BMP、GIF和JPEG文件格式简介及相互转换图象文件就是描绘了一幅图象的计算机磁盘文件。形成数字图象数据后,将其存储在计算机里的方法有2种,即位映射和向量处理方式。我们这里主要讨论的是位图。不同图象软件几乎都用各种的方法处理图象,图象格式也多种多样,它主要包括文件识别头和图象数据。文件识别头用来让计算机判断是哪种文件格式,图象数据包含了整个对图象描绘相关数据,包括调色板、位图映象等。根据压缩算法不同,映象方式也不同,下面简要介绍一下压缩算法。一、 行程长度压缩原理是将一扫描行中的颜色值相同的相邻像素用一个计数值和那些像素的颜色值来代替。例如:aaabccccccddeee,则可用3a1b6c2d3e来代替。对于拥有大面积,相同颜色区域的图像,用RLE压缩方法非常有效。由RLE原理派生出许多具体行程压缩方法:1.PCX行程压缩方法: 该算法实际上是位映射格式到压缩格式的转换算法,该算法对于连续出现1次的字节Ch,若Ch&0xc0则压缩时在该字节前加上0xc1,否则直接输出Ch,对于连续出现N 次的字节Ch,则压缩成0xc0+N,Ch这两个字节,因而N最大只能为ff-c0=3fh(十进制为63),当N大于63时, 则需分多次压缩。2.BI_RLE8压缩方法:在WINDOWS的位图文件中采用了这种压缩方法。该压缩方法编码也是以两个字节为基本单位。其中第一个字节规定了用第二个字节指定的颜色重复次数。 如编码 0504表示从当前位置开始连续显示5个颜色值为04的像素。当第二个字节为零时第二个字节有特殊含义:0表示行末;1表示图末;2转义后面2个字节,这两个字节分别表示下一像素相对于当前位置的水平位移和垂直位移。这种压缩方法所能压缩的图像像素位数最大为8位(256色)图像。3.BI_RLE压缩方法: 该方法也用于WINDOWS位图文件中,它与 BI_RLE8编码类似,唯一不同是:BI_RLE4的一个字节包含了两个像素的颜色,因此,它只能压缩的颜色数不超过16的图像。因而这种压缩应用范围有限。4.紧缩位压缩方法(Packbits):该方法是用于Apple公司的Macintosh机上的位图数据压缩 方法, TIFF 规范中使用了这种方法, 这种压缩方法与BI_RLE8压缩方法相似,如1c1c1c 压缩为:83 1c 21 81 32 56 48,显而易见, 这种压缩方法最好情况是每连续128个字节相同,这128个字节可压缩为一个数值7f。这种方法还是非常有效的。二、霍夫曼编码压缩:也是一种常用的压缩方法。是1952年为文本文件建立的,其基本原理是频繁使用的数据用较短的代码代替,很少使用的数据用较长的代码代替,每个数据的代码各不相同。这些代码都是二进制码,且码的长度是可变的。如: 有一个原始数据序列,ABACCDAA则编码为A(0),B(10),C(110),(D111),压缩后为100。产生霍夫曼编码需要对原始数据扫描两遍,第一遍扫描要精确地统计出原始数据中的每个值出现的频率,第二遍是建立霍夫曼树并进行编码,由于需要建立二叉树并遍历二叉树生成编码,因此数据压缩和还原速度都较慢,但简单有效,因而得到广泛的应用。
请登录后再发表评论!您还未登陆,请登录后操作!
压缩软件的实际意义是什么
请教压缩是不是文件经过压缩以后可以减少占用空间,能够减少多少,还是有其他别的什么意义。谢谢
可以减少占用空间,还有文件打包的作用
计算机处理的信息是以二进制数的形式表示的,因此压缩软件就是把二进制信息中相同的字符串以特殊字符标记来达到压缩的目的。为了有助于理解文件压缩,请您在脑海里想象一幅蓝天白云的图片。对于成千上万单调重复的蓝色像点而言,与其一个一个定义“蓝、蓝、蓝……”长长的一串颜色,还不如告诉电脑:“从这个位置开始存储1117个蓝色像点”来得简洁,而且还能大大节约存储空间。这是一个非常简单的图像压缩的例子。其实,所有的计算机文件归根结底都是以“1”和“0”的形式存储的,和蓝色像点一样,只要通过合理的数学计算公式,文件的体积都能够被大大压缩以达到“数据无损稠密”的效果。总的来说,压缩可以分为有损和无损压缩两种。如果丢失个别的数据不会造成太大的影响,这时忽略它们是个好主意,这就是有损压缩。有损压缩广泛应用于动画、声音和图像文件中,典型的代表就是影碟文件格式MPEG、音乐文件格式MP3和图像文件格式JPG。
  很多人都惊异于压缩技术的神奇,一个文件被压缩成一半大小,何以能无损还原呢?
  早期使用的压缩技术都基于统计模
可以减少占用空间,还有文件打包的作用
计算机处理的信息是以二进制数的形式表示的,因此压缩软件就是把二进制信息中相同的字符串以特殊字符标记来达到压缩的目的。为了有助于理解文件压缩,请您在脑海里想象一幅蓝天白云的图片。对于成千上万单调重复的蓝色像点而言,与其一个一个定义“蓝、蓝、蓝……”长长的一串颜色,还不如告诉电脑:“从这个位置开始存储1117个蓝色像点”来得简洁,而且还能大大节约存储空间。这是一个非常简单的图像压缩的例子。其实,所有的计算机文件归根结底都是以“1”和“0”的形式存储的,和蓝色像点一样,只要通过合理的数学计算公式,文件的体积都能够被大大压缩以达到“数据无损稠密”的效果。总的来说,压缩可以分为有损和无损压缩两种。如果丢失个别的数据不会造成太大的影响,这时忽略它们是个好主意,这就是有损压缩。有损压缩广泛应用于动画、声音和图像文件中,典型的代表就是影碟文件格式MPEG、音乐文件格式MP3和图像文件格式JPG。
  很多人都惊异于压缩技术的神奇,一个文件被压缩成一半大小,何以能无损还原呢?
  早期使用的压缩技术都基于统计模型,到20世纪80年代初基于字典压缩的新技术才慢慢推广开来。
  数据压缩包含了非常多的软件和硬件技术,这些技术各不相同,但是大多数压缩软件都是基于LZ77、LZ88算法并加以修正而成,而LZ77是字典压缩的起源。大家都知道一个文本文件是由一些单词组成,而且必定有重复现象发生,例如我们这里经常出现的“压缩软件”一词,压缩的原理就是在文件的头部做一个类似字典的东西,把“压缩软件”这个词放在“字典”中,并为这个词指定一个占较少字节数的编码,而文章中的“压缩软件” 一词均用此编码代替,以达到压缩的目的。当然压缩软件在实际运作中并非如此简单,还要使用一些看了就头痛的演算方法,在此就不一一细述。也许有人会问,文本文件可用字典技术,那其它文件怎么办呢。这就无须操心了,因为对于压缩软件来说,一个文件中的“数据压缩”一词和“@#¥%^” 是一样的,关键在于冗余码(重复部分)的多少。
  压缩常识
  按压缩方式分:有所谓的“透明压缩”和“打包压缩”。
  “透明压缩”一般针对.exe和.com文件,直接压缩。成功的话,文件体积变小,功能不变,运行速度还可能更快。但是,这种压缩方法的对象面很窄。如果压缩失败,还会造成文件不可用。所以,这一类程序总是强烈要求用户在压缩前将文件备份。
  “打包压缩”就是现在常提到的压缩软件使用的压缩法。它把一个或多个文件压缩成一个文件——压缩包。要使用压缩后的文件,必须先解压将文件复原。它的特点是风险小,适用于减小不常用的文件所占空间和传输数据。当然,按照压缩算法,我们还可以将压缩分成很多种。
  一般我们在谈到压缩时,会提到许多相关术语,下面我们就提出一些常见的术语进行解释。
  压缩格式:压缩文件时使用的压缩编码方法不同,压缩生成的文件结构就不同,这种压缩文件结构就称压缩格式。
  压缩比率:文件压缩后占用的磁盘空间与原文件的比率称压缩比率。在常用的压缩格式中,RAR格式压缩比率较高,ZIP格式较低。但ZIP格式的文件操作速度较快。
  解压:将压缩文件还原为本来的文件格式,也称释放、扩展。
  压缩包:一般将通用压缩格式的文件称为压缩包,如ZIP格式压缩文件。这种文件可以在压缩工具的管理下对包中压缩的文件进行管理,如查看、删除、添加等。
  打包:将文件压缩成通用压缩格式的压缩包文件称为打包,也指将文件压缩添加到压缩包。
  多卷压缩:将压缩的文件包分成几个压缩文件称为多卷压缩,一般是为了将压缩文件储存在多个软磁盘上或方便网上传输。
  自解压文件:将文件压缩生成可执行的文件,然后在没有压缩工具的帮助下,通过执行压缩的文件,就可将自己的源文件解压还原出来。
回答数:1078
的初衷目的就是压缩软件,减少内存空间!便于上传、携带、发送。
您的举报已经提交成功,我们将尽快处理,谢谢!你的位置: &&
哈弗曼压缩与解压的原理及对象化实现
哈弗曼压缩与解压的原理及对象化实现
这一次主要是跟大家探讨一下哈弗曼压缩的原理及实现,由于过程化的实现更加容易理解也更加直观,所以这里首先会分步骤跟大家讲解一下哈弗曼压缩的具体实现方法,然后再与大家分享一下对象化的实现。 & & & 首先,我们要知道文件为什么能压缩? & & & 文件是由字节所组成的,一个字节的长度为8位,所以最多只存在256种字节,而一个文件中一般存在许多相同的字节,我们把相同的字节以一种更加精简的方式表示,就完成了我们所说的压缩。 & & & 哈弗曼压缩的原理是什么? & & & 上次博客中提到了哈弗曼编码,但是只是粗略的带过了,这一次举一个具体的例子来更加直观的说明哈弗曼压缩的原理。 & & & 假设一个文件中是这样的一串字节ABBCCCDDDD,那么这个文件的大小就是10个byte。那么接下来就是我们的哈弗曼压缩的第一步:一.读取文件,统计每一种字节出现的次数,将出现的字节种类与对应的次数保存起来(可采用数组或者是HashMap,或者是其他的数据结构)保存完了之后干什么呢??当然是构建哈弗曼树呀。第二步:二. 利用得到的字节与对应的频次构建哈弗曼树,需要注意的是,构建树的时候是以字节出现的频次作为我们的评判标准,出现次数越多的放在越上层。比如我们上面所说的这个文件,它所构成的树应该是这样的:我们现在得到的树还处于未编码的状态,那么第三步毫无疑问就是我们所说的编码了:三. 将得到的哈弗曼树进行编码编码之后的树就变成这个样子了(采取向左编1的方式):到了这一步其实我们的压缩就已经完成一半了,听到这里,你可能纳闷了,不对呀,不是还没开始么?? & & & 下面我们就来看一下哈弗曼压缩的精华所在: & & & 编码之后,A所对应的的编码就是111,B就是110,C是10,D是0,那么我们的文件就变成了1,是不是有一种亲切感?下面只要把这些10串每8个作为一组编码成一个新的字节(2进制转10进制),我们的压缩工作就大功告成了,所以这里每8位我也特别用逗号表示出来了,怎么样一个10个byte的文件瞬间变成了3个byte,是不是很神奇呢? & & & 等一下,做到这一步其实是远远不够的,有几个问题:1. & & & 怎么样把这一串的01变成我们所说的byte数?需要注意的是,我们把文件中的字节变成这个样子只是把它们变成了一个01的字符串,那么这个问题就要用编程方法来解决了,具体方法有很多种,下面会给大家介绍一两种。2.如果最后几位不满8个怎么办? & & & 我们可以定义这样一个规则,在最后的位置补0,在文件的末尾再加一位表示最后一个数补0的个数,这样的话这个问题就变得很简单了。3. 压缩之后我们怎么知道压缩前每种字节对应的编码是什么样子的? & & & 如果你理解了压缩的前三步,你一定会想到这个问题,确实,我们如果按照这种方式压缩,我们所得到的文件将会无法复原。那么要完成压缩,最关键的一步,还要将压缩时所得到的每个字节对应的码表写入文件,这样我们才能保证,我们所做的工作是可逆的。 & & & 好的,说完了这些,压缩剩下来的步骤相信你也已经明了了,压缩第四步:四.根据每种字节对应的哈弗曼编码,将文件转换成01字符串五.将得到的01串重新编码成新的byte数组写入文件 & & & 当然,第四步与第五步可以同时完成,而且,每生成8个以上的字符串就将其前8位转换成byte数组的效率要比一次性转换的效率要高,这是因为,当文件转换成编码之后,长度增大,JVM中需要开辟一个很大的内存空间去存放这个字符串,这显然是很耗时的。不过在过程化实现的代码中,楼主并没有将这一层优化,具体的优化工作需要读者们自己去做。下面就是过程化实现的代码了:Java代码package 哈弗曼压缩;
* 哈弗曼压缩
* @author 陈强
import java.io.F
import java.io.FileInputS
import java.io.FileOutputS
import java.io.InputS
import java.io.OutputS
import java.util.ArrayL
import java.util.HashM
import java.util.I
import java.util.PriorityQ
import java.util.S
public class HFMCondense {
public static void main(String args[]){
String file="D://b.txt";
HFMCondense condense=new HFMCondense();
//System.out.println("元素与对应的频次表:");
//System.out.println(condense.readFiletoMap(file));
//System.out.println("生成的哈弗曼树");
HFMNode hfmTree=condense.HashMapToHFMTree(condense.readFiletoMap(file));
//condense.PreOrderTraverse(hfmTree);
//System.out.println();
//System.out.println("产生的哈弗曼编码表:");
//condense.HuffmanCode(hfmTree,"");
condense.HuffmanCoding(hfmTree, "");
//转译后的字符串
//String codeString=condense.FileToString(file);
//System.out.println(codeString);
//压缩后的字符串
//String newString=new String(condense.createByteArray(codeString));
//System.out.println(newString);
System.out.println("开始压缩...");
long start=System.currentTimeMillis();
//System.out.println(condense.FileToString(file));
//System.out.println(condense.CodeToString(file));
//pressFile(condense.createByteArray(condense.CodeToString(file)),"D://c");
pressFile(condense.createByteArray(condense.FileToString(file)),"D://c");
System.out.println("压缩结束...用时:"+(System.currentTimeMillis()-start));
//打印数组最后一个补0的个数
//byte content[]=condense.createByteArray(condense.FileToString(file));
//System.out.println(content[content.length-2]);
* 读取将要被压缩的文件,统计每一个字符出现的频率,并将得到的内容存入HashMap中
* @param fileName 将要被压缩的文件
* @return 每一个字节数出现的频率所对应的HashMap
public HashMap&Byte,Integer& readFiletoMap(String fileName){
HashMap&Byte,Integer& hashMap=new HashMap&Byte,Integer&();
File file=new File(fileName);
if(file.exists()){
InputStream in=new FileInputStream(file);
//创建与文件大小相同的字节数组
byte[] content=new byte[in.available()];
//读取文件
in.read(content);
//存入HashMap中
for(int i=0;i&content.i++){
//如果表中存在某一个键
if(hashMap.containsKey(content[i])){
//获取该字节当前的键值
int rate=hashMap.get(content[i]);
//键值增大
hashMap.put(content[i], rate);
//如果不存在某一个字节对象,则将它存入HashMap当中
hashMap.put(content[i],1);
in.close();
}catch(Exception e){
e.printStackTrace();
System.out.println("文件不存在");
return hashM
* 将HashMap中的元素取出来封装到哈弗曼树中,树中叶子结点保存的是HashMap中的每一个键值与频率
* @param map 读取的Map
哈夫曼树的根结点
public HFMNode HashMapToHFMTree(HashMap&Byte,Integer& map){
//得到存储键值的系
Set&Byte& keys=map.keySet();
//得到迭代器对象
Iterator&Byte& iter=keys.iterator();
//如果还有值
while(iter.hasNext()){
byte key=iter.next();//获取系中的键
int value=map.get(key);//得到该键出现的频率
//创建结点并将结点对象加入到队列当中
HFMNode node=new HFMNode(key,value);
nodeQueue.add(node);
nodeList.add(node);
//当所剩的结点数还大于两个
while(nodeQueue.size()&=2){
//得到键值频率最小的两个结点
HFMNode left=nodeQueue.poll();
HFMNode right=nodeQueue.poll();
//将这两个结点组合起来生成新的结点
HFMNode node=new HFMNode(left.data,left.value+right.value,left,right);
nodeQueue.add(node);
//获取队列中的最后一个结点作为根结点
HFMNode hfm=nodeQueue.poll();
* 为生成的哈弗曼树进行编码,产生对应的哈弗曼编码表
* @param hfm
对应的哈弗曼树
* @param code 对应生成的哈弗曼编码
* @return 哈弗曼编码表
//创建一个新的哈弗曼编码表
HashMap&Byte,String& codeMap=new HashMap&Byte,String&();
public HashMap&Byte,String& HuffmanCoding(HFMNode hfm,String code){
//如果左子树不为空,则左子树编码加1
if(hfm.lchild!=null){
HuffmanCoding(hfm.lchild,code+"1");
//如果右子树不为空,则右子树编码加0
if(hfm.rchild!=null){
HuffmanCoding(hfm.rchild,code+"0");
//如果到达叶子结点,则将元素放入HashMap中生成哈弗曼编码表
if(hfm.lchild==null&&hfm.rchild==null){
codeMap.put(hfm.data,code);
return codeM
* 将哈弗曼编码转换成字符串
* @param fileName 读取的文件名
* @return 编码之后的哈弗曼字符串
public String CodeToString(String fileName){
File file=new File(fileName);
String codeString="";
//如果文件存在
if(file.exists()){
InputStream in=new FileInputStream(file);
byte content[]=new byte[in.available()];
in.read(content);
int len=content.//得到文件的字节长度
int size=nodeList.size();//得到队列的长度
while(i&len){
for(int j=0;j&j++){
if(content[i]==nodeList.get(j).data){
codeString+=nodeList.get(j).
in.close();
}catch(Exception e){
e.printStackTrace();
System.out.println("文件不存在");
return codeS
* 将文件按照对应的哈弗曼编码表转成01字符串
* @param fileName 读入的文件名
* @return 转译后的字符串
public String FileToString(String fileName){
File file=new File(fileName);
String StringContent="";
//如果文件存在
if(file.exists()){
InputStream in=new FileInputStream(file);
byte content[]=new byte[in.available()];
in.read(content);
//循环转译
int len=content.
for(int i=0;i&i++){
StringContent+=codeMap.get(content[i]);
in.close();
}catch(Exception e){
e.printStackTrace();
System.out.println("文件不存在");
return StringC
* 将转译后的01字符串重新转换后放入新的字节数组当中
* @param code 转译后的01字符串
* @return 新的字节数组,里面包含了压缩后的字节内容
public byte[] createByteArray(String code) {
//将每8位字符分隔开来得到字节数组的长度
int size=code.length()/8;
//截取得到字符串8整数后的最后几个字符串
String destString=code.substring(size*8);
byte dest[]=destString.getBytes();
//s用来记录字节数组的单字节内容
int s = 0;
int temp = 0;
// 将字符数组转换成字节数组,得到字符的字节内容,方便将二进制转为十进制
byte content[] = code.getBytes();
for (int k = 0; k & content. k++) {
content[k] = (byte) (content[k] - 48);
//转译后的字节内容数组
byte byteContent[];
if (content.length % 8 == 0) {// 如果该字符串正好是8的倍数
byteContent = new byte[content.length / 8 + 1];
byteContent[byteContent.length - 1] = 0;// 那么返回的字节内容数组的最后一个数就补0
//否则该数组的最后一个数就是补0的个数
byteContent = new byte[content.length / 8 + 2];
byteContent[byteContent.length - 1] = (byte) (8 - content.length % 8);
int bytelen=byteContent.
int contentlen=content.
// byteContent数组中最后一个是补0的个数,实际操作到次后个元素
//Math.pow返回第一个参数的第二个参数次幂的值
while (i & bytelen - 2) {
for (int j = 0; j & j++) {
if (content[j] == 1) {// 如果数组content的值为1
s =(int)(s + Math.pow(2, (7 - (j - 8 * i))));// 累积求和
if ((j+1)%8==0) {// 当有8个元素时
byteContent[i] = (byte)// 就将求出的和放入到byteContent数组中去
s = 0;// 并重新使s的值赋为0
int destlen=dest.
for(int n=0;n&n++){
temp+=(dest[n]-48)*Math.pow(2, 7-n);//求倒数第2个字节的大小
byteContent[byteContent.length - 2] = (byte)
return byteC
* 压缩并输出新文件
* @param content 压缩后产生的新的字节数组
* @param fileName 输出文件名
public void CompressFile(byte[] content,String fileName){
File file=
//统一后缀名
if(!fileName.endsWith("hfm")){
file=new File(fileName+".hfm");
}else if(fileName.endsWith("hfm")){
file=new File(fileName);
int len=content.
if(len&0){
OutputStream out=new FileOutputStream(file);
//将字节内容写入文件
out.write(content);
out.close();
}catch(Exception e){
e.printStackTrace();
System.out.println("压缩出错");
* 测试一下哈弗曼树建立是否正确
* @param hfm
public void PreOrderTraverse(HFMNode hfm){
if(hfm!=null){
System.out.print(hfm.value+" ");
PreOrderTraverse(hfm.lchild);
PreOrderTraverse(hfm.rchild);
* 存储哈弗曼树结点的优先队列
ArrayList&HFMNode& nodeList=new ArrayList&HFMNode&();
PriorityQueue&HFMNode& nodeQueue=new PriorityQueue&HFMNode&(11,new MyComparator());
* 实例化的一个比较器类
class MyComparator implements Comparator&HFMNode&{
public int compare(HFMNode o1, HFMNode o2) {
return o1.value-o2.
}结点类: Java代码
&&作者:cq520 &&
最新热门tag

我要回帖

更多关于 压缩卷是什么意思 的文章

 

随机推荐