zoukankan      html  css  js  c++  java
  • [Zlib]_[0基础]_[使用zlib库压缩文件]


    场景:

    1. WIndows上没找到系统提供的win32 api来生成zip压缩文件, 有知道的大牛麻烦留个言。

    2. zlib比較经常使用,编译也方便,使用它来做压缩吧。

    MacOSX平台默认支持zlib库.

    http://zlib.net

    3. zlib库里的 srccontribminizipminizip.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 <vector>
    #include <string>
    
    //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<std::string> 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 <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #include <errno.h>
    #include <fcntl.h>
    
    #include <direct.h>
    #include <io.h>
    
    #include "zlib.h"
    
    #include "zip.h"
    
    #ifdef _WIN32
    #define USEWIN32IOAPI
    #include "iowin32.h"
    #endif
    
    #define WRITEBUFFERSIZE (16384)
    #define MAXFILENAME (256)
    
    
    
    
    #ifdef _WIN32
    
    static char* Utf8ToAnsi(const char* utf8)  
    {  
    	// 先转换为UNICODE
        int dwUnicodeLen = MultiByteToWideChar(CP_UTF8,0,utf8,-1,NULL,0);  
        if(!dwUnicodeLen)  
        {  
            return strdup(utf8);  
        }  
        size_t num = dwUnicodeLen*sizeof(wchar_t);  
        wchar_t *pwText = (wchar_t*)malloc(num+2);  
        memset(pwText,0,num+2);  
        MultiByteToWideChar(CP_UTF8,0,utf8,-1,pwText,dwUnicodeLen);
    	
    	// 再转换为ANSI
    	int len;  
        len = WideCharToMultiByte(CP_ACP, 0, pwText, -1, NULL, 0, NULL, NULL);  
        char *szANSI = (char*)malloc(len + 1);  
        memset(szANSI, 0, len + 1);  
        WideCharToMultiByte(CP_ACP, 0, pwText, -1, szANSI, len, NULL,NULL);  
    
    	free(pwText);
        return (char*)szANSI;  
    } 
    
    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
    ",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;
    		}
    		// 这个版本号不支持UTF8字符串的正确存储,所以要转换为ANSI显示.
    		char* pos_ansi = Utf8ToAnsi(pos);
    		err = zipOpenNewFileInZip3_64(zf,pos_ansi,&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); free(pos_ansi); if (err != ZIP_OK) { printf("error in opening %s in zipfile ",pos); } else { fin = ZipFopen(filenameinzip,"rb"); if (fin==NULL) { err=ZIP_ERRNO; printf("error in opening %s for reading ",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 ",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 ", 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 ",filenameinzip); } } } errclose = zipClose(zf,NULL); if (errclose != ZIP_OK) { printf("error in closing %s ",output_path); return false; } return true; }


    注意: 再链接项目时假设报错, 那么就是由于你没加预编译宏 ZLIB_WINAPI

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

    完整项目下载地址:

    http://download.csdn.net/detail/infoworld/9482396 (1.1 解决中文名在zip里的显示问题)

    2017.3.5 更新

    [Zlib]_[0基础]_[使用zlib库压缩文件夹]


  • 相关阅读:
    MybatisPlus学习笔记4:全局策略配置
    函数的参数
    函数参数作业
    函数基本使用的作业
    函数的基本使用
    文件处理作业
    文件处理b模式和指针
    用户登入注册作业
    文件处理作业
    文件处理
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/6821823.html
Copyright © 2011-2022 走看看