场景:

1. 解压文件一般用在下载了一个zip文件之后解压,或者分析某个文件须要解压的操作上.

2. 解压文件,特别是解压带目录的zip文件往往系统没有提供这类Win32 API,当然C#自带库能解压, 当然这里仅仅讨论C/C++, 像C#和Java这样的开挂的标准库不在考虑范围内.

3. zlib解压文件的使用样例在 contrib\minizip 样例里. 这里基本是直接提取miniunz.c 的代码进行封装解压就可以, 仅仅是改了下支持中文路径.

主文件 zip_util.cpp

#include "stdafx.h"

#include "zip_util.h"
#include "unzip.h" #include <iostream>
#include <string>
#include <algorithm>
#include <stdlib.h> #include <zlib.h>
#include "ioapi.h"
#include "iowin32.h"
#include "wrap_object.h" using namespace std; #define CASESENSITIVITY (0)
#define WRITEBUFFERSIZE (8192)
#define MAXFILENAME (256) unzFile ZipUtil::UnzOpen64(const wchar_t* path)
{
zlib_filefunc64_def ffunc;
fill_win32_filefunc64W(&ffunc);
unzFile zf = unzOpen2_64(path,&ffunc);
return zf;
} char* ConvertUnicodeToUtf8(const wchar_t* unicode)
{
if(unicode == NULL)
{
return strdup("\0");
} int len;
len = WideCharToMultiByte(CP_UTF8, 0,unicode, -1, NULL, 0, NULL, NULL);
char *szUtf8 = (char*)malloc(len + 1);
memset(szUtf8, 0, len + 1);
WideCharToMultiByte(CP_UTF8, 0,unicode, -1, szUtf8, len, NULL,NULL);
return szUtf8;
} wchar_t* ConvertUtf8ToUnicode(const char* utf8)
{
if(!utf8)
{
wchar_t* buf = (wchar_t*)malloc(2);
memset(buf,0,2);
return buf;
}
int nLen = ::MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,(LPCSTR)utf8,-1,NULL,0);
//返回须要的unicode长度
WCHAR * wszUNICODE = new WCHAR[nLen+1];
memset(wszUNICODE, 0, nLen * 2 + 2);
nLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)utf8, -1, wszUNICODE, nLen); //把utf8转成unicode
return wszUNICODE;
} void change_file_date( const char *filename,uLong dosdate,tm_unz tmu_date)
{
HANDLE hFile;
FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; wchar_t* filenamew = ConvertUtf8ToUnicode(filename);
hFile = CreateFile(filenamew,GENERIC_READ | GENERIC_WRITE,
0,NULL,OPEN_EXISTING,0,NULL);
GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);
LocalFileTimeToFileTime(&ftLocal,&ftm);
SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
CloseHandle(hFile);
free(filenamew); } int mymkdir(const char* dirname)
{
wchar_t* dirnamew = ConvertUtf8ToUnicode(dirname);
int res = CreateDirectory(dirnamew,NULL);
free(dirnamew);
return res;
} int makedir (const char *newdir)
{
char *buffer ;
char *p;
int len = (int)strlen(newdir); if (len <= 0)
return 0; buffer = (char*)malloc(len+1);
memset(buffer,0,len+1); if (buffer==NULL)
{
printf("Error allocating memory\n");
return UNZ_INTERNALERROR;
}
strcpy(buffer,newdir); if (buffer[len-1] == '/' || buffer[len-1] == '\\') {
buffer[len-1] = '\0';
}
if (mymkdir(buffer) == 0)
{
free(buffer);
return 1;
} p = buffer+1;
while (1)
{
char hold; while(*p && *p != '\\' && *p != '/')
p++;
hold = *p;
*p = 0;
if ((mymkdir(buffer) == -1) && (errno == ENOENT))
{
printf("couldn't create directory %s\n",buffer);
free(buffer);
return 0;
}
if (hold == 0)
break;
*p++ = hold;
}
free(buffer);
return 1;
} int do_extract_currentfile(unzFile uf,const int* popt_extract_without_path,
int* popt_overwrite,const char* password,const char* dir)
{
char filename_inzip[256];
char* filename_withoutpath;
char* p;
int err=UNZ_OK;
FILE *fout=NULL;
void* buf;
uInt size_buf; unz_file_info64 file_info;
uLong ratio=0;
err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0); if (err!=UNZ_OK)
{
printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
return err;
} size_buf = WRITEBUFFERSIZE;
buf = (void*)malloc(size_buf);
if (buf==NULL)
{
printf("Error allocating memory\n");
return UNZ_INTERNALERROR;
} std::string dir1(dir);
dir1.append(filename_inzip);
strncpy(filename_inzip,dir1.c_str(),sizeof(filename_inzip)); p = filename_withoutpath = filename_inzip;
while ((*p) != '\0')
{
if (((*p)=='/') || ((*p)=='\\'))
filename_withoutpath = p+1;
p++;
} if ((*filename_withoutpath)=='\0')
{
if ((*popt_extract_without_path)==0)
{
printf("creating directory: %s\n",filename_inzip);
mymkdir(filename_inzip);
}
}
else
{
const char* write_filename;
int skip=0; if ((*popt_extract_without_path)==0)
write_filename = filename_inzip;
else
write_filename = filename_withoutpath; wchar_t* write_filenamew = ConvertUtf8ToUnicode(write_filename);
WrapMalloc wm_filename(write_filenamew);
err = unzOpenCurrentFilePassword(uf,password);
if (err!=UNZ_OK)
{
printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
} if ((skip==0) && (err==UNZ_OK))
{
fout=_wfopen(write_filenamew,L"wb"); /* some zipfile don't contain directory alone before file */
if ((fout==NULL) && ((*popt_extract_without_path)==0) &&
(filename_withoutpath!=(char*)filename_inzip))
{
char c=*(filename_withoutpath-1);
*(filename_withoutpath-1)='\0';
makedir(write_filename);
*(filename_withoutpath-1)=c;
fout = _wfopen(write_filenamew,L"wb");
} if (fout==NULL)
{
printf("error opening %s\n",write_filename);
}
} if (fout!=NULL)
{
printf(" extracting: %s\n",write_filename); do
{
err = unzReadCurrentFile(uf,buf,size_buf);
if (err<0)
{
printf("error %d with zipfile in unzReadCurrentFile\n",err);
break;
}
if (err>0)
if (fwrite(buf,err,1,fout)!=1)
{
printf("error in writing extracted file\n");
err=UNZ_ERRNO;
break;
}
}
while (err>0);
if (fout)
fclose(fout); if (err==0)
change_file_date(write_filename,file_info.dosDate,
file_info.tmu_date);
} if (err==UNZ_OK)
{
err = unzCloseCurrentFile (uf);
if (err!=UNZ_OK)
{
printf("error %d with zipfile in unzCloseCurrentFile\n",err);
}
}
else
unzCloseCurrentFile(uf); /* don't lose the error */
} free(buf);
return err;
} int do_extract( unzFile uf,
int opt_extract_without_path,
int opt_overwrite,const char* password,const char* dir)
{
uLong i;
unz_global_info64 gi;
int err;
FILE* fout=NULL; err = unzGetGlobalInfo64(uf,&gi);
if (err!=UNZ_OK)
printf("error %d with zipfile in unzGetGlobalInfo \n",err); for (i=0;i<gi.number_entry;i++)
{
if (do_extract_currentfile(uf,&opt_extract_without_path,
&opt_overwrite,
password,dir) != UNZ_OK)
return 0; if ((i+1)<gi.number_entry)
{
err = unzGoToNextFile(uf);
if (err!=UNZ_OK)
{
printf("error %d with zipfile in unzGoToNextFile\n",err);
return 0;
}
}
} return 1;
} bool ZipUtil::UnzipFile(std::wstring zip_file,std::wstring unzip_dir)
{
if(unzip_dir[unzip_dir.size()-1] != L'\\')
{
unzip_dir.append(L"\\");
}
int err = UNZ_OK; // error status
uInt size_buf = WRITEBUFFERSIZE; // byte size of buffer to store raw csv data
void* buf; // the buffer
string sout; // output strings
char filename_inzip[256]; // for unzGetCurrentFileInfo
unz_file_info file_info; // for unzGetCurrentFileInfo unzFile uf = UnzOpen64(zip_file.c_str()); // open zipfile stream
if (uf==NULL) {
wcerr << "Cannot open " << zip_file << endl;
return false;
} // file is open
CreateDirectory(unzip_dir.c_str(),NULL);
char* utf8 = ConvertUnicodeToUtf8(unzip_dir.c_str());
int ret_value = do_extract(uf,0,0,NULL,utf8);
unzClose(uf);
free(utf8);
return ret_value;
}

完整项目下载地址:

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

[zlib]_[0基础]_[使用Zlib完整解压zip内容]的更多相关文章

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

    场景: 1. WIndows上没找到系统提供的win32 api来生成zip压缩文件, 有知道的大牛麻烦留个言. 2. zlib比較经常使用,编译也方便,使用它来做压缩吧. MacOSX平台默认支持z ...

  2. [libcurl]_[0基础]_[使用libcurl下载大文件]

    场景: 1. 在Windows编程时, 下载http页面(html,xml)能够使用winhttp库,可是并非非常下载文件,由于会失败. 由此引出了WinINet库,无奈这个库的稳定性比較低,使用样例 ...

  3. [Windows]_[0基础]_[Release程序的崩溃报告minidump解决方式]

    场景: 1. Release的程序崩溃时,崩溃报告能够让开发者查明代码哪里出了问题,用处大大的. 2. 仅仅实用VS的编译器才支持,所以MinGW就无缘了. 3. 使用了未处理异常过滤处理函数. 4. ...

  4. [wxWidgets]_[0基础]_[经常更新进度条程序]

    场景: 1. 非常根据程序的进展需要处理业务,以更新进度条,进度条的目的是为了让用户知道业务流程的进度.一个进度条程序更友好,让用户知道在程序执行.不是没有反应. 2. 现在更新见过这两种方法的进展. ...

  5. [C/C++标准库]_[0基础]_[使用fstream合并文本文件]

    场景: 1. 就是合并文本文件,而且从第2个文件起不要合并第一行. 2. 多加了一个功能,就是支持2个以上的文件合并. 3. 问题: http://ask.csdn.net/questions/192 ...

  6. [ATL/WTL]_[0基础]_[CBitmap复制图片-截取图片-平铺图片]

    场景: 1.当你须要截取图片部分区域作为某个控件的背景. 2.须要平铺图片到一个大区域让他自己主动放大时. 3.或者须要合并图片时. 代码: CDC sdc; CDC ddc; sdc.CreateC ...

  7. [C/C++标准库]_[0基础]_[交集和补集]

    场景: 1. 计算std::vector A和 std::vector B里的同样的元素, 用于保留不删除. 2. 计算std::vector A和 std::vector B里各自的补集, 用于删除 ...

  8. [C/C++标准库]_[0基础]_[优先队列priority_queue的使用]

    std::priority_queue 场景: 1. 对于一个任务队列,任务的优先级由任务的priority属性指明,这时候就须要优先级越高的先运行.而queue并没有排序功能,这时priority_ ...

  9. [网络]_[0基础]_[使用putty备份远程数据]

    场景: 1. putty是windows上訪问linux服务的免费client之中的一个.用它来ssh到远程server备份数据是常见的做法(在没做好自己主动备份机制前), 通过putty界面尽管也不 ...

随机推荐

  1. Python动态属性和特性(二)

    内置的property经常用作装饰器,但它其实是一个类.在Python中,函数和类通常可以互换,因为二者都是可调用对象,而且没有实例化的new运算符,所以调用构造方法和调用工厂函数没有区别,只要能返回 ...

  2. 03009_HttpServletResponse

    1.HttpServletResponse概述 (1)我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参数,一个为代表请求的request和 ...

  3. Java集合数据类型

    Java集合如Map.Set.List等所有集合只能存放引用类型数据,它们都是存放引用类型数据的容器,不能存放如int.long.float.double等基础类型的数据. 1. 集合存储对象 Jav ...

  4. 大数据学习——akka自定义RPC

    实现 package cn.itcast.akka import akka.actor.{Actor, ActorSystem, Props} import akka.actor.Actor.Rece ...

  5. Linux中的more命令

    ore命令,功能类似 cat , cat命令是整个文件的内容从上到下显示在屏幕上.  more会以一页一页的显示方便使用者逐页阅读,而最基本的指令就是按空白键(space)就往下一页显示,而且还有搜寻 ...

  6. [luoguP2764] 最小路径覆盖问题(最大流 || 二分图最大匹配)

    传送门 可惜洛谷上没有special judge,不然用匈牙利也可以过的,因为匈牙利在增广上有一个顺序问题,所以没有special judge就过不了了. 好在这个题的测试数据比较特殊,如果是网络流的 ...

  7. P4513 小白逛公园 (线段树)

    题目链接 Solution 线段树是一门比较刁钻的手艺... 此题我们需要维护 \(4\) 个变量: \(amx\) 代表当前节点的最大值. \(lmx\) 代表当前节点以左端点为起点的区间最大值. ...

  8. net5:Theme主题样式的动态变换,在内容页content中操作影响模板页的操作

    原文发布时间为:2008-07-29 -- 来源于本人的百度文章 [由搬家工具导入] using System;using System.Data;using System.Configuration ...

  9. 解决Ubuntu系统中文乱码显示问题

    sudo dpkg-reconfigure locales最后重启ubuntu. 重启后在系统设置--语言设置里面需要勾选中文,就会自动下载中文包,安装完成后再次重启就ok了.

  10. C#中IPAddress类/Dns类/IPHostEntry类/IPEndPoint用法简介

    C#中IPAddress类/Dns类/IPHostEntry类/IPEndPoint用法简介 IP是一种普遍应用于因特网.允许不同主机能够相互找到对方的寻址协议.IP地址由4个十进制的数字号码所组成, ...