A. 数据流压缩原理和数据压缩Zlib的实现
压缩的本质就是去冗余,去除信息冗余,使用最短的编码保存最完整的数据信息。所以对于不同的场景,压缩采用的算法也因时制宜,比如视频和图片可以采用有损压缩,而文本数据采用无损压缩。压缩率又取决于信息的冗余度,也就是内容中重复的比例。那些均匀分布的随机字符串,压缩率会降到最低,即香农限
deflate是zip文件的默认算法。它更是一种数据流压缩算法。
LZ77压缩算法采用字典的方式进行压缩,是一种简单但是很高效的数据压缩算法。其方式就是把数据中一些可以组织成短语的字符加入字典。维护三个概念: 短语字典、滑动窗口、向前缓冲区
压缩的逆过程,通过解码标记和保持滑动窗口中的符号来更新解压数据。当解码字符被标记:将标记编码成字符拷贝到滑动窗口中,一步一步直到全部翻译完成
在流式传输中,不定长编码数据的解码想要保持唯一性,必须满足唯一可以码的条件。而异前缀码就是一种唯一可译码的候选,当然这样会增加编码的长度,却可以简化解码。
huffman编码是一种基于概率分布的贪心策略最优前缀码。huffman编码可以有效的压缩数据,压缩率取决于数据本身的信息冗余度
计算数据中各符号出现的概率,根据概率从小到大,从下往上反向构建构造码树,这样最终得到的编码的平均长度是最短的。同时也是唯一可译的
解读:在一开始,每一个字符已经按照出现概率的大小排好顺序,在后续的步骤中,每一次将概率最低的两棵树合并,然后用合并后的结果再次排序(为了找出最小的两棵树)。在gzip源码中并没有专门去排序,而是使用专门的数据结构(比如最小堆或者红黑树)。
使用优先队列实现huffman树,最后基于Huffman树最终实现文件压缩。 具体步骤:
gzip = gzip 头 + deflate 编码的实际内容 + gzip 尾
zlib = zlib 头 + deflate 编码的实际内容 + zlib 尾
压缩之前:初始化各种输入输出缓冲区; 压缩:我们可以不断往这些缓冲区中填充内容,然后由deflate函数进行压缩或者indeflate函数进行解压
总结:在调用deflate函数之前,应用程序必须保证至少一个动作被执行(avail_in或者avail_out被设置),用提供更多数据或者消耗更多的数据的方式。avail_out在函数调用之前千万不能为零。应用程序可以随时消耗被压缩的输出数据
B. C++语言怎么用zlib库来解压.ISO或.zip文件
下面是使用zlib库的压缩和解压缩演示代码:#include <stdlib.h>#include <stdio.h>#include <zlib.h>int main(int argc, char* argv[]){FILE* file;uLong flen;unsigned char* fbuf = NULL;uLong clen;unsigned char* cbuf = NULL;/* 通过命令行参数将srcfile文件的数据压缩后存放到dstfile文件中 */if(argc < 3){printf("Usage: zcdemo srcfile dstfile\n");return -1;}if((file = fopen(argv[1], "rb")) == NULL){printf("Can\'t open %s!\n", argv[1]);return -1;}/* 装载源文件数据到缓冲区 */fseek(file, 0L, SEEK_END); /* 跳到文件末尾 */flen = ftell(file); /* 获取文件长度 */fseek(file, 0L, SEEK_SET);if((fbuf = (unsigned char*)malloc(sizeof(unsigned char) * flen)) == NULL){printf("No enough memory!\n");fclose(file);return -1;}fread(fbuf, sizeof(unsigned char), flen, file);/* 压缩数据 */clen = compressBound(flen);if((cbuf = (unsigned char*)malloc(sizeof(unsigned char) * clen)) == NULL){printf("No enough memory!\n");fclose(file);return -1;}if(compress(cbuf, &clen, fbuf, flen) != Z_OK){printf("Compress %s failed!\n", argv[1]);return -1;}fclose(file);if((file = fopen(argv[2], "wb")) == NULL){printf("Can\'t create %s!\n", argv[2]);return -1;}/* 保存压缩后的数据到目标文件 */fwrite(&flen, sizeof(uLong), 1, file); /* 写入源文件长度 */fwrite(&clen, sizeof(uLong), 1, file); /* 写入目标数据长度 */fwrite(cbuf, sizeof(unsigned char), clen, file);fclose(file);free(fbuf);free(cbuf);return 0;}
C. 如何发挥zlib压缩解压的最大效
首先说明,这里不是横向比较zlib与别的引擎(rar,leo,powerarc…),是探索如何发挥zlib压缩/解压的最大效率。先看看如下代码在效率上的差异:var MS:TMemoryStream;(1):begin MS:=TMemoryStream.Create; MS.Size:=$400000;//4M————————————————(2):var i:integer;begin MS:=TMemoryStream.Create; for i:=1 to 1024 do MS.Size:=MS.Size+4096; 你会发现,方法(1)只要1个毫秒,方法(2)却要20秒。因此,如果把解压缩程序写成下面这样,会非常没有效率:procere ZlibDeCompress(instream,outStream:TStream);var ACS:TDeCompressionStream; buf:array[1..4096] of byte; numread:integer;begin inStream.Position:=0; ACS:=TDeCompressionStream.Create(inStream); try repeat numRead:=ACS.Read(buf,sizeof(buf)); if numread>0 then outStream.Write(buf,numRead); until (numRead=0); finally ACS.Free; end;end;如果我们知道原始资料的大小,一次确定outStream.Size,效率就可以提高几十倍。方法很简单,我们可以在压缩时,把原始资料的Size写在压缩Stream的头部,如,写一个Longword的大小,解压时就可以先读出Size,因此,最有效率的解压程序为:procere ZlibDecompressStream2(Source,Dest:TMemoryStream);var zstream: TZStreamRec; SourceLen,DestLen:LongWord;begin FillChar(zstream,SizeOf(TZStreamRec),0); SourceLen:=Source.Size; Source.Position:=0; Source.Read(DestLen,SizeOf(LongWord)); Dest.Size:=DestLen; zstream.next_in:=Pointer(LongWord(Source.Memory)+SizeOf(LongWord)); zstream.avail_in:=SourceLen-SizeOf(LongWord); zstream.next_out:=Dest.Memory; zstream.avail_out:=DestLen; ZDecompressCheck(InflateInit(zstream)); try ZDecompressCheck(inflate(zstream,Z_NO_FLUSH)); finally ZDecompressCheck(inflateEnd(zstream)); end;end;用一个4M的文件试试,效率提高近70倍。同样道理,在压缩的时候,如果能预先知道压缩后的大小,也能提高效率不少,但这似乎是不可能的,也不能盲目的给outStream.Size一个"足够大"的数值,只能按引擎的原理估算一个最接近的数值,zlib推荐的为:((SourceLen+(SourceLen div 10)+12)+255) and not 255因此,最有效率的压缩程序为:procere ZlibCompressStream2(Source,Dest:TMemoryStream; CompressLevel:TZCompressi);var zstream: TZStreamRec; SourceLen,DestLen:LongWord;begin FillChar(zstream,SizeOf(TZStreamRec),0); SourceLen:=Source.Size; DestLen:=SizeOf(LongWord)+((SourceLen+(SourceLen div 10)+12)+255) and not 255; Dest.Size:=DestLen; Dest.Position:=0; Dest.Write(SourceLen,Sizeof(LongWord)); zstream.next_in:=Source.Memory; zstream.avail_in:=SourceLen; zstream.next_out:=Pointer(LongWord(Dest.Memory)+SizeOf(LongWord)); zstream.avail_out:=DestLen-SizeOf(longWord); ZCompressCheck(DeflateInit(zstream,ZLevels[CompressLevel])); try ZCompressCheck(deflate(zstream,Z_FINISH)); finally ZCompressCheck(deflateEnd(zstream)); end; Dest.Size:=zstream.total_out+SizeOf(LongWord);end;
D. 简单介绍VC++6.0下如何使用压缩库ZLIB(转)
2. 用VC++6.0打开先来看看 zlib 都提供了那些函数, 都在zlib.h中,看到一堆宏不要晕,其实都是为了兼容各种编译器和一些类型定义.死死抓住那些主要的函数的原型声明就不会受到这些东西的影响了.关键的函数有那么几个:(1)int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);把源缓冲压缩成目的缓冲, 就那么简单, 一个函数搞定(2) int compress2 (Bytef *dest, uLongf *destLen,const Bytef *source, uLong sourceLen,int level);功能和上一个函数一样,都一个参数可以指定压缩质量和压缩数度之间的关系(0-9)不敢肯定这个参数的话不用太在意它,明白一个道理就好了: 要想得到高的压缩比就要多花时间(3) uLong compressBound (uLong sourceLen);计算需要的缓冲区长度. 假设你在压缩之前就想知道你的产度为 sourcelen 的数据压缩后有多大, 可调用这个函数计算一下,这个函数并不能得到精确的结果,但是它可以保证实际输出长度肯定小于它计算出来的长度(4) int uncompress (Bytef *dest, uLongf *destLen,const Bytef *source, uLong sourceLen);解压缩(看名字就知道了:)(5) deflateInit() + deflate() + deflateEnd()3个函数结合使用完成压缩功能,具体用法看 example.c 的 test_deflate()函数. 其实 compress() 函数内部就是用这3个函数实现的(工程 zlib 的 compress.c 文件)(6) inflateInit() + inflate() + inflateEnd()和(5)类似,完成解压缩功能.(8) 其他诸如获得版本等函数就不说了.
E. java 如何用zlib解压缩tar.gz文件
public static void makeZip(List<File> fileList,String zipPath,boolean isDelete) { byte[] buf = new byte[1024]; try { // Create the ZIP file File zipFile = new File(zipPath); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile)); // Compress the files for (int i = 0; i < fileList.size(); i++) { FileInputStream in = new FileInputStream(fileList.get(i)); // Add ZIP entry to output stream. out.putNextEntry(new ZipEntry(fileList.get(i).getName())); // Transfer bytes from the file to the ZIP file int len; while ( (len = in.read(buf)) > 0) { out.write(buf, 0, len); } // Complete the entry out.closeEntry(); in.close(); } // Complete the ZIP file out.close(); System.out.println("压缩完成."); //把旧的文件删除 if(isDelete == true){ for (int i = 0; i < fileList.size(); i++) { File oldFile = fileList.get(i); oldFile.delete(); } } } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args){ File in1=new File("D:\\a.txt"); File in2=new File("D:\\b.txt"); File[] file=new File[]{in1,in2}; File zip=new File("D:\\ab.zip"); IDMZip mgr=new IDMZip(); mgr.ZipFiles(file, zip); }这个方法不管你是在windows下还是在linux下,都能正常执行。
F. 关于zlib解压缩的问题~
压缩与解压缩的时候,分别有2个不同的版本,分别是safe和普通的版本。2个版本要对应起来。你在解压缩的时候,注意缓冲区大小了吗?缓冲区够用了吗?在压缩前,保存一下这个压缩前的原始的长度,然后解压前,分配一块至少这么大的内存。你实际调试过吗?比如,你可以先去掉文件IO的过程,只是对一个字符串进行压缩/解压,然后看看是否正确;然后再加上文件IO,看看存取的过程是否正确。压缩后的文件应该以二进制方式打开对吧。
G. 如何使用Zlib解压内存块中的文件
1 准备工作。下载zlib.dll。以及相关头文件。将dll文件及头文件加入工程。2 压缩:调用函数compress.形式为int compress(Byte * dest, uLong* destLen, const Byte *source, ULONG sourceLen);功能是将source指向的空间,长度为sourceLen的数据进行压缩,压缩数据储存在dest中,长度由参数destLen返回。如果压缩出错,返回对应错误号,否则返回0.3解压缩:调用函数uncompress.形式为int uncompress(Byte * dest, uLong* destLen, const Byte *source, ULONG sourceLen);功能是将source指向的空间,长度为sourceLen的数据进行解压缩,解压缩后的数据储存在dest中,长度由参数destLen返回。如果解压缩出错,返回对应错误号,否则返回0.
H. 我要使用zlib库压缩文件,例如word文档,png图片等,那要用哪一个函数呢compress函数只能压缩里面的内容!
如果有足够的缓存,可以一次性地压缩整个文件,这时候使用compress()压缩,如果缓存比较小,使用defalate()函数在循环里面压缩.
I. 如何用zlib将很多文件或一个文件夹压缩
新建一个文件夹,把需要压缩的东西拖到新建文件夹里,然后对着文件夹点右键,选择添加到压缩文件或者其他压缩命令,在弹出的界面里点击确定
J. 关于使用 Zlib + minizip 解压带有密码的 zip 文件
这里只说 Zlib 在 Windows 上的编译. Linux/Mac 上的不再本次考虑范围内. 使用zlib库解压*.zip文件