1. 程式人生 > >使用開源庫zlib壓縮和解壓檔案

使用開源庫zlib壓縮和解壓檔案

zlib,一個十分強大的開源壓縮解壓庫,應用示範廣泛,很多開源庫中都有它的存在(libpng,libzplay,ffmpeg……)。

作為普通開發者只要掌握其主要的兩個函式就足夠用了:

int compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);

compress函式將 source 緩衝區中的內容壓縮到 dest 緩衝區。 sourceLen 表示

source 緩衝區的大小(以位元組計)。注意函式的第二個引數 destLen 是傳址呼叫。當呼叫函式時,destLen表示 dest 緩衝區的大小,destLen > (sourceLen + 12)*100.1%。

int uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);

uncompress 函式將 source 緩衝區的內容解壓縮到 dest 緩衝區。sourceLen 是

source 緩衝區的大小(以位元組計)。注意函式的第二個引數 destLen 是傳址呼叫。當呼叫函式時,destLen 表示 dest 緩衝區的大小, dest 緩衝區要足以容下解壓後的資料。

在進行解壓縮時,需要提前知道被壓縮的資料解壓出來會有多大。這就要求在進行壓縮之前,儲存原始資料的大小(也就是解壓後的資料的大小)。這不是 zlib 函式庫的功能,需

要我們做額外的工作。當函式退出後, destLen 是解壓出來的資料的實際大小。

看一個小例子:

/ zlibDemo.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include "zlib.h"
#include <assert.h>
#include <Windows.h>
#include <iostream>
using std::cout;
using std::endl;
//靜態載入如下:
//#pragma comment(lib,"zlib1")
const char* pFileCom="..\\Debug\\save.xml";//原始檔
const char* pFileSave="..\\Debug\\1.zip";//壓縮後的檔案
#define MAX_LEN 1024*100//本例只適用於小於100KB的檔案
int _tmain(int argc, _TCHAR* argv[])
{
	//壓縮檔案
	FILE* fp1=NULL;
	fp1=fopen(pFileCom,"rb");
	assert(fp1);
	//申請緩衝區
	unsigned char* pBufferRes=new unsigned char[MAX_LEN];
	unsigned char* pBufferDes=new unsigned char[MAX_LEN];
	//置零
	memset(pBufferRes,0,MAX_LEN);
	memset(pBufferDes,0,MAX_LEN);
	//讀取整個檔案到緩衝區
	fread(pBufferRes,sizeof(unsigned char),MAX_LEN-1,fp1);
	uLongf lSize=strlen((const char*)pBufferRes);
	//動態載入DLL
	HINSTANCE hIns=::LoadLibrary(_T("..\\Debug\\zlib1.dll"));
	uLongf desLen;
	if(hIns)
	{
		typedef int (*fun)(Bytef*,uLongf*,const Bytef*,uLongf);
		fun f=NULL;
		//指向函式地址的指標
		f=(fun)GetProcAddress(hIns,"compress");
		if(f==NULL)
		{
			cout<<"獲取模組函式地址失敗!"<<endl;
			::FreeLibrary(hIns);
			return 1;
		}
		int nError=f(pBufferDes,&desLen,pBufferRes,lSize);
		//desLen必須大於lsize,詳情請參照zlib文件
		if(nError!=Z_OK)
		{
			cout<<"壓縮失敗!"<<endl;
			::FreeLibrary(hIns);
			fclose(fp1);
			return 1;
		}
		cout<<"壓縮成功,壓縮率為: %"<<desLen/(float)lSize*100<<endl;
	}
	else
	{
		cout<<"載入庫檔案失敗!"<<endl;
		return 1;
	}
	fclose(fp1);
	FILE* fp2=NULL;
	fp2=fopen(pFileSave,"wb");
	//將壓縮後的資訊寫入檔案
	fwrite(pBufferDes,sizeof(unsigned char),desLen,fp2);
	fclose(fp2);
	/////////////////////////////////////////////////////////////////////////////////////////////////
	//解壓檔案
	memset(pBufferDes,0,MAX_LEN);
	memset(pBufferRes,0,MAX_LEN);
	fp1=fopen("..\\Debug\\1.zip","rb");
	desLen=fread(pBufferRes,1,desLen,fp1);
	typedef int (*unFun)(Bytef*,uLongf*,const Bytef*,uLongf);
	unFun uf=NULL;
	uf=(unFun)GetProcAddress(hIns,"uncompress");
	uLongf unSize;
	if(uf)
	{
		int nRet=uf(pBufferDes,&unSize,pBufferRes,desLen);
		::FreeLibrary(hIns);
		if(nRet!=Z_OK)
		{
			cout<<"解壓縮失敗"<<endl;
			fclose(fp1);
			return 1;
		}
	}
	fclose(fp1);
	fp2=fopen("..\\Debug\\uncompress.xml","wb");
	fwrite(pBufferDes,1,unSize,fp2);
	fclose(fp2);
	cout<<"成功解壓檔案"<<pFileSave<<"到uncompress.xml"<<endl;
	//釋放申請的記憶體空間
	delete[] pBufferDes;
	pBufferDes=NULL;
	delete[] pBufferRes;
	pBufferRes=NULL;
	return 0;
}

/*zlib中兩個主要函式的宣告:
int compress OF((Bytef *dest,   uLongf *destLen,const Bytef *source, uLong sourceLen));
int uncompress OF((Bytef *dest,   uLongf *destLen,const Bytef *source, uLong sourceLen));*/


執行程式,結果如下:

下載地址: