程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> [C/C++]_[初級]_[使用zlib庫壓縮文件]

[C/C++]_[初級]_[使用zlib庫壓縮文件]

編輯:C++入門知識

[C/C++]_[初級]_[使用zlib庫壓縮文件]



場景:

1. WIndows上沒找到系統提供的win32 api來生成zip壓縮文件, 有知道的大牛麻煩留個言。

2. zlib比較常用,編譯也方便,使用它來做壓縮吧。MacOSX平台默認支持zlib庫.

http://zlib.net

3. zlib庫裡的 src\contrib\minizip\minizip.c 裡有壓縮例子, 我現在使用的是zlib 1.2.5,用vs2010編譯完。下載地址:

http://download.csdn.net/detail/infoworld/8177625

4. 自己封裝了一下ZipHelper便於使用,首先先得編譯zlib為dll版本, 這個類就是刪減了minizip.c的一些東西, 支持中文路徑,項目需要目前只支持一級目錄,如果有子目錄的也不難,自己改改吧。

5. 使用方式, 注意, 路徑字符串必須是utf8格式編碼, 編譯時要加上預編譯宏 ZLIB_WINAPI

ZipHelper z;
z.AddFile(utf8_path1);
z.AddFile(utf8_path2);
z.ToZip(utf8_output_zip_path);


6. MacOSX沒測過,理論上應該可以編譯過。

zip_helper.h

#ifndef __ZIP_HELPER
#define __ZIP_HELPER

#include 
#include 

//1.暫時不支持子目錄
//注意: 因為使用了zlib庫,使用時加上預編譯宏 ZLIB_WINAPI
class ZipHelper
{
public:
	ZipHelper(){}
	~ZipHelper(){}

	//path: utf8 path
	ZipHelper& AddFile(const char* input_path);
	//output_path :utf8 path
	bool ToZip(const char* output_path);

private:
	std::vector files_;
};


#endif

zip_helper.cpp

#include "zip_helper.h"


#ifndef _WIN32
#ifndef __USE_FILE_OFFSET64
#define __USE_FILE_OFFSET64
#endif
#ifndef __USE_LARGEFILE64
#define __USE_LARGEFILE64
#endif
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#ifndef _FILE_OFFSET_BIT
#define _FILE_OFFSET_BIT 64
#endif
#endif

#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 

#include "zlib.h"

#include "zip.h"

#ifdef _WIN32
#define USEWIN32IOAPI
#include "iowin32.h"
#endif

#define WRITEBUFFERSIZE (16384)
#define MAXFILENAME (256)




#ifdef _WIN32
static wchar_t* QXUtf82Unicode(const char* utf)  
{  
	if(!utf || !strlen(utf))  
	{  
		return NULL;  
	}  
	int dwUnicodeLen = MultiByteToWideChar(CP_UTF8,0,utf,-1,NULL,0);  
	size_t num = dwUnicodeLen*sizeof(wchar_t);  
	wchar_t *pwText = (wchar_t*)malloc(num);  
	memset(pwText,0,num);  
	MultiByteToWideChar(CP_UTF8,0,utf,-1,pwText,dwUnicodeLen);  
	return pwText;  
} 

static FILE* ZipFopen(const char* path,const char* mode)
{
	wchar_t* path_u = QXUtf82Unicode(path);
	wchar_t* mode_u = QXUtf82Unicode(mode);
	FILE* file = _wfopen(path_u,mode_u);
	free(path_u);
	free(mode_u);
	return file;
}

/* name of file to get info on */
/* return value: access, modific. and creation times */
/* dostime */
uLong filetime(const char* f, tm_zip *tmzip, uLong *dt)          
{
	int ret = 0;
	{
		FILETIME ftLocal;
		HANDLE hFind;
		WIN32_FIND_DATA ff32;
		wchar_t *unicode = QXUtf82Unicode(f);
		hFind = FindFirstFile(unicode,&ff32);
		if (hFind != INVALID_HANDLE_VALUE)
		{
			FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
			FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
			FindClose(hFind);
			ret = 1;
		}
		free(unicode);
	}
	return ret;
}
#else
#define ZipFopen fopen;
#endif

ZipHelper& ZipHelper::AddFile(const char* input_path)
{
	files_.push_back(input_path);
	return *this;
}

bool ZipHelper::ToZip(const char* output_path)
{
	int err=0;
	zipFile zf;
	int errclose;
	int opt_compress_level = Z_DEFAULT_COMPRESSION;
#ifdef USEWIN32IOAPI
	zlib_filefunc64_def ffunc;
	fill_win32_filefunc64W(&ffunc);
	wchar_t* temp_path = QXUtf82Unicode(output_path);
	zf = zipOpen2_64(temp_path,APPEND_STATUS_CREATE,NULL,&ffunc);
	free(temp_path);
#else
	zf = zipOpen64(output_path,APPEND_STATUS_CREATE);
#endif

	if (zf == NULL)
	{
		printf("error opening %s\n",output_path);
		err= ZIP_ERRNO;
		return false;
	}

	int size = files_.size();
	void* buf = NULL;
	int size_buf = WRITEBUFFERSIZE;
    buf = (void*)malloc(size_buf);
	for (int i = 0; i < size; ++i)
	{
		FILE * fin;
		int size_read;
		const char* filenameinzip = files_[i].c_str();
		const char *savefilenameinzip;
		zip_fileinfo zi;
		unsigned long crcFile=0;
		int zip64 = 0;

		zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
			zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
		zi.dosDate = 0;
		zi.internal_fa = 0;
		zi.external_fa = 0;
		filetime(filenameinzip,&zi.tmz_date,&zi.dosDate);

		savefilenameinzip = filenameinzip;
		const char* pos = NULL;
		
		if( (pos = strrchr(savefilenameinzip,'\\')) 
			|| (pos = strrchr(savefilenameinzip,'/')) )
		{
			pos++;
		}else
		{
			pos = savefilenameinzip;
		}

		err = zipOpenNewFileInZip3_64(zf,pos,&zi,
			NULL,0,NULL,0,NULL,
			(opt_compress_level != 0) ? Z_DEFLATED : 0,
			opt_compress_level,0,
			-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
			NULL,crcFile, zip64);

		if (err != ZIP_OK)
		{
			printf("error in opening %s in zipfile\n",pos);
		}
		else
		{
			fin = ZipFopen(filenameinzip,"rb");
			if (fin==NULL)
			{
				err=ZIP_ERRNO;
				printf("error in opening %s for reading\n",filenameinzip);
			}
		}

		if (err == ZIP_OK)
			do
			{
				err = ZIP_OK;
				size_read = (int)fread(buf,1,size_buf,fin);
				if (size_read < size_buf)
				{
					if (feof(fin)==0)
					{
						printf("error in reading %s\n",filenameinzip);
						err = ZIP_ERRNO;
					}
				}
				if (size_read>0)
				{
					err = zipWriteInFileInZip (zf,buf,size_read);
					if (err<0)
					{
						printf("error in writing %s in the zipfile\n",
							filenameinzip);
					}
				}
			} while ((err == ZIP_OK) && (size_read>0));

			if(fin)
			{
				fclose(fin);
			}

			if (err<0)
			{
				err=ZIP_ERRNO;
			}
			else
			{
				err = zipCloseFileInZip(zf);
				if (err!=ZIP_OK)
				{
					printf("error in closing %s in the zipfile\n",filenameinzip);
				}

			}
	}
	errclose = zipClose(zf,NULL);
	if (errclose != ZIP_OK)
	{
		printf("error in closing %s\n",output_path);
		return false;
	}
	return true;
}

注意: 再鏈接項目時如果報錯, 那麼就是因為你沒加預編譯宏 ZLIB_WINAPI

1>zip_helper.obj : error LNK2001: 無法解析的外部符號 _zipClose



  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved