lzma sdk文件压缩与解压

来源:互联网 发布:移动硬盘恢复软件 编辑:程序博客网 时间:2024/06/11 19:45

最新版的lzma sdk可以去SourceForge上面获取,具体地址为点击打开链接

7z官网点击打开链接(英文版)点击打开链接(中文版)


我用lzma sdk主要是为了用来压缩和解压文件用的,其实适当的用法可以用来制作安装包,因为安装包也是一种能自己解压的压缩文件,其实也叫自解压压缩包,使用一些知名的压缩软件都有这些功能,当然,界面也是单调的,想要自定义安装界面只能自己压缩和解压,然后界面自己定义了。

好了,废话不多说,上主菜吧,lzma sdk的使用:

我在官网下载的最新版lzma sdk 15.12,也是最近更新的版本,解压之后有如下文件:


不要被这么多文件吓到了,其实主要用到的也只是C那个文件夹里面的东西,C文件夹里面主要放的是lzma sdk的算法实现,当然Asm文件夹里面也是放的算法实现,不过是用汇编实习的,这个博客主要是介绍C\C++使用lzma sdk,所有直接用C那个文件夹里面的,进入C文件夹主要有如下文件:


像这些基本上都给你实现和封装好了,直接等你去用就行了,很简单的,主要用的的函数定义在LzmaLib.h里面,实现在LzmaLib.c里面。

现在打开LzmaLib.h文件,你会发现只定义了两个函数,一个是压缩函数,一个是解压函数,而且还有对于参数的使用说明。

压缩函数:

MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,  unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */  int level,      /* 0 <= level <= 9, default = 5 */  unsigned dictSize,  /* default = (1 << 24) */  int lc,        /* 0 <= lc <= 8, default = 3  */  int lp,        /* 0 <= lp <= 4, default = 0  */  int pb,        /* 0 <= pb <= 4, default = 2  */  int fb,        /* 5 <= fb <= 273, default = 32 */  int numThreads /* 1 or 2, default = 2 */  );
解压函数:
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,  const unsigned char *props, size_t propsSize);
其实,在函数列出来的时候参数该怎么传递lzma的作者都已经写在函数里了,可谓是方便了使用者啊,点个赞大笑

接下来就是如何使用这两个函数了。其实,在C\Util\LzmaLib这个路径下有个lzmalib工程,作者用的VC6写的,所有提供的是VC6的工作空间:


作用为导出刚刚介绍的两个函数到dll里面,当然你也可以改改工程制作成静态库,这里就不赘述了,直接用VC6打开LzmaLib.dsw,然后构建一个dll来用吧。

默认工程生成的dll不在工程目录里面,在C盘下面,具体路径为C:\Util\LZMA.dll,当然有用的还是这两个文件,用depends查看下dll的导出函数

确实是刚刚提到的两个函数。

好了,说了这么多废话,现在开始使用lzma sdk来压缩东西了。我这边就不限制使用什么工程了,只教如何使用,不管你使用的什么库,用lzma sdk都是一样的有,准备好dll和lib文件还有相关头文件。头文件只需要lzmalib.h就行了,注意要把文件开头的#include "7zTypes.h"删掉,EXTERN_C_BEGIN改成extern "C"{(有花括号),EXTERN_C_END改成}。#define MY_STDAPI int MY_STD_CALL改成#define MY_STDAPI int _stdcall,LzmaUncompress函数的第四个参数SizeT改成size_t,这样才能编译通过,还有记得链接静态库,不然也是会报错的。VC的编译器可以直接在源码里面加上一句#pragma comment(lib,"LzmaLib.lib")就能解决了。好了,准备工作做的差不多了。开始使用步骤了。

压缩函数用到的参数为字节数据,所有现在就要获得文件的字节数据,由于程序定义之初并不知道文件的大小,所有读取文件字节数据的时候采用动态内存分配,分配的内存大小就是文件的大小,所有最开始获取的是文件大小。当然,这个文件大小在解压的时候也用到了,所有在生存压缩之后的文件的时候也一并把文件大小给存进去,解压的时候好操作。现在开始就是读取文件的大小,如果你用的是C语言的话,可以使用fopen打开文件,然后用fseek到文件末尾,用ftell获取文件大小,然后rewind,使文件指针指向文件开始的地方。C++里面就是文件流了。不过原理都一样,这里就不赘述了。获取到文件大小之后就是动态分配内存了(不知道的可以去恶补C\C++知识了偷笑),然后读取文件字节数据到刚刚分配的内存里面,然后调用LzmaCompress压缩。这里压缩的时候有一点要提的就是LzmaCompress函数获取到的unsigned char *outProps这个在解压的时候也有用,所有要连同文件大小一起写进去。下面是我的代码,仅供参考。

压缩:

#include <iostream>#include <fstream>#include "LzmaLib.h"#pragma comment(lib,"LZMA.lib")using namespace std;int main(void){ifstream in("QtGui4.dll",ios::binary|ios::in);//以二进制读的形式打开文件in.seekg(0,in.end);//使流指针指向文件尾unsigned int size_src = in.tellg();//获取文件大小,单位:字节in.seekg(0,in.beg);//使流指针指向文件头cout<<hex<<size_src<<endl;//输出文件大小unsigned int size_des = size_src;unsigned char *buffer_src = new unsigned char[size_src];//分配内存,存储读的文件的字节数据unsigned char *buffer_des = new unsigned char[size_des];//分配内存,因为压缩后的文件大小并不知道,但是绝对不会超过原来文件的大小,//如果超过了就不是压缩了,那估计就是解压了,所以也当做原来文件大小处理。memset(buffer_src,0,size_src);memset(buffer_des,0,size_src);//内存清零,清除掉那些内存垃圾数据,全部填充0in.read((char *)buffer_src,size_src);//读取数据到内存unsigned char outProps[5]={0};//我也不知道这是什么,反正很有用的说。size_t outPropsSize = 5;/*LzmaCompress最后7个参数int level,0 <= level <= 9, default = 5unsigned dictSize,default = (1 << 24)int lc,0 <= lc <= 8, default = 3int lp,0 <= lp <= 4, default = 0int pb,0 <= pb <= 4, default = 2int fb,5 <= fb <= 273, default = 32int numThreads1 or 2, default = 2*/LzmaCompress(buffer_des,//目标内存地址&size_des,//目标内存大小buffer_src,//源数据内存地址size_src,//源数据内存大小outProps,//按照要求传参&outPropsSize,//按照要求传参5,(1<<24),3,0,2,32,2);ofstream out("QtGui4.dll.lzma",ios::binary|ios::out);//以二进制读的形式写文件out.write((char *)(&size_src),4);//把文件大小写到文件最开始4个字节out.write((char *)outProps,5);//PROPS写到接下来的5个字节out.write((char *)buffer_des,size_des);//写压缩后的数据//收尾处理out.close();delete[] buffer_des;delete[] buffer_src;in.close();return 0;}
解压:
#include <iostream>#include <fstream>#include "LzmaLib.h"#pragma comment(lib,"LZMA.lib")using namespace std;int main(void){ifstream in("QtGui4.dll.lzma",ios::binary|ios::in);//以二进制读的形式打开文件in.seekg(0,in.end);//使流指针指向文件尾unsigned int size_src = in.tellg();//获取文件大小,单位:字节in.seekg(0,in.beg);//使流指针指向文件头cout<<hex<<size_src<<endl;//输出文件大小unsigned int size_des = 0;in.read((char *)(&size_des),4);cout<<hex<<size_des<<endl;//输出读取的数据,在压缩的时候保存着未压缩之前的大小unsigned char outProps[5]={0};//我也不知道这是什么,只知道解压的时候要用的压缩的时候获取的in.read((char *)outProps,5);size_src = size_src - 4 - 5;//实际的压缩数据是从第9个字节之后的,因为开始的4个字节存储的原始文件大小,//接下来5个字节存储的是PROPS。unsigned char *buffer_src = new unsigned char[size_src];unsigned char *buffer_des = new unsigned char[size_des];memset(buffer_src,0,size_src);memset(buffer_des,0,size_des);in.read((char *)buffer_src,size_src);//获取到压缩数据,以便进行解压LzmaUncompress(buffer_des,&size_des,buffer_src,&size_src,outProps,5);ofstream out("QtGui4.dll",ios::binary|ios::out);out.write((char *)buffer_des,size_des);out.close();delete[] buffer_src;delete[] buffer_des;in.close();return 0;}

2 0
原创粉丝点击