最近因为项目的需要,要对zip压缩文件进行批量解压。在网上查阅了相关的资料后,最终使用zlib开源库实现了该功能。本文将对zlib开源库进行简单介绍,并给出一个使用zlib开源库对zip压缩文件进行解压的示例程序。

1.zlib开源库

  zlib是应用最广泛的压缩与解压缩zip文件的免费开源库,提供了数据压缩与解压缩的函式库。

  zlib中最关键的函数有以下两个:

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

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

  其中,函数compress()用于将源缓冲区数据压缩到目的缓冲区,函数uncompress()用于将源缓冲区数据解压到目的缓冲区。

  由此可见,zlib只是一个针对gzip以及deflate算法的库,用于将一段内存压缩/解压之后放到另一段内存上,这离压缩/解压文件甚至文件夹的目标还很远。但是,它提供了一个叫做minizip的例子给出了操作zip文件的方法。

2.minizip简介

  minizip是zlib的上层库,它封装了与zip文件相关的操作。

  minizip中与解压缩相关的API有以下几个:

  (1)unzFile unzOpen(const char *path);

  (2)int unzClose(unzFile file);

  (3)int unzGetGlobalInfo(unzFile file, unz_global_info *pglobal_info);

  (4)int unzGoToNextFile(unzFile file);

  (5)int unzGetCurrentFileInfo(unzFile file, unz_file_info *pfile_info, char *szFileName, uLong fileNameBufferSize,

void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize);

  (6)int unzOpenCurrentFile(unzFile file);

  (7)int unzCloseCurrentFile(unzFile file);

  (8)int unzReadCurrentFile(unzFile file, voidp buf, unsigned len);

  有了以上这些API,我们就可以对zip文件进行解压缩了。一个完整的解压过程应该包含以下这些步骤:

  (1)调用unzOpen()函数打开一个zip压缩文件,其参数是zip压缩文件的路径。

  (2)调用unzGetGlobalInfo()函数来获取zip压缩文件的一些信息(如内部文件个数等),这些信息会保存在传入参数pglobal_info中。

  (3)然后开始遍历zip文件中的内部文件,初始时会自动定位到第一个内部文件,处理完一个内部文件后可以使用unzGoToNextFile()函数来跳转到下一个内部文件。

  (4)对于每个内部文件来说,可以先调用unzGetCurrentFileInfo()函数来获取该内部文件信息(如文件的路径、文件大小等),这些信息会保存在传入参数pfile_info中。

  (5)调用unzOpenCurrentFile()函数打开该内部文件。

  (6)调用unzReadCurrentFile()函数读取该内部文件内容。

  (7)该内部文件读取完毕之后,调用unzCloseCurrentFile()函数对内部文件进行关闭。

  (8)zip文件中的所有内部文件遍历完成之后,调用unzClose()函数关闭打开的zip压缩文件。

3.示例程序

  了解了以上的内容之后,我们就可以编写程序使用zlib以及minizip对zip压缩文件进行解压缩了。

3.1加载相关的头文件及库文件

  在使用zlib以及minizip之前,我们需要加载相关的头文件及库文件到工程中。需要加载的头文件有zlib.h、unzip.h、zip.h。需要加载的库文件有zlib.lib、minizip.lib。需要添加的动态链接库zlib1.dll。这些文件都可以从网上下载得到。

     #include "zlib/zlib.h"
#include "zlib/unzip.h"
#include "zlib/zip.h"
#pragma comment(lib, "zlib.lib")
#pragma comment(lib, "minizip.lib")

3.2配置工程

  因为zlib以及minizip是用C语言编写的,在VC6.0中使用时,需要对工程进行如下配置,否则会出现编译链接通不过的问题。

  (1)在“工程”、“设置”中选择“连接”标签页,在“分类”中选择输入,在“忽略库”中加入MSVCRT。

  (2)在“工程”、“设置”中选择“C/C++”标签页,在“分类”中选择Code Generation,在“Use run-time library”中选择“Debug Multithreaded DLL”。

  (3)在“工程”、“设置”中选择“C/C++”标签页,在“分类”中选择常规,在“预处理程序定义”中加入_AFXDLL。

3.3示例程序

  如下的示例程序演示了如何调用minizip中的API对zip文件进行解压。

 /*
* 函数功能 : 解压zip文件
* 备 注 : 参数strFilePath表示zip压缩文件的路径
* 参数strTempPath表示要解压到的文件目录
* 作 者 : 博客园 依旧淡然(http://www.cnblogs.com/menlsh/)
*/
void CZlibDemoDlg::UnzipFile(CString strFilePath, CString strTempPath)
{
int nReturnValue; //打开zip文件
unzFile unzfile = unzOpen(strFilePath);
if(unzfile == NULL)
{
MessageBox("打开zip文件失败!", "提示", MB_OK|MB_ICONWARNING);
return;
} //获取zip文件的信息
unz_global_info* pGlobalInfo = new unz_global_info;
nReturnValue = unzGetGlobalInfo(unzfile, pGlobalInfo);
if(nReturnValue != UNZ_OK)
{
MessageBox("获取zip文件信息失败!", "提示", MB_OK|MB_ICONWARNING);
return;
} //解析zip文件
unz_file_info* pFileInfo = new unz_file_info;
char szZipFName[MAX_PATH]; //存放从zip中解析出来的内部文件名
for(int i=; i<pGlobalInfo->number_entry; i++)
{
//解析得到zip中的文件信息
nReturnValue = unzGetCurrentFileInfo(unzfile, pFileInfo, szZipFName, MAX_PATH,
NULL, , NULL, );
if(nReturnValue != UNZ_OK)
{
MessageBox("解析zip文件信息失败!", "提示", MB_OK|MB_ICONWARNING);
return;
} //判断是文件夹还是文件
switch(pFileInfo->external_fa)
{
case FILE_ATTRIBUTE_DIRECTORY: //文件夹
{
CString strDiskPath = strTempPath + _T("//") + szZipFName;
CreateDirectory(strDiskPath, NULL);
}
break;
default: //文件
{
//创建文件
CString strDiskFile = strTempPath + _T("//") + szZipFName;
HANDLE hFile = CreateFile(strDiskFile, GENERIC_WRITE,
, NULL, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
MessageBox("创建文件失败!", "提示", MB_OK|MB_ICONWARNING);
return;
} //打开文件
nReturnValue = unzOpenCurrentFile(unzfile);
if(nReturnValue != UNZ_OK)
{
MessageBox("打开文件失败!", "提示", MB_OK|MB_ICONWARNING);
CloseHandle(hFile);
return;
} //读取文件
const int BUFFER_SIZE = ;
char szReadBuffer[BUFFER_SIZE];
while(TRUE)
{
memset(szReadBuffer, , BUFFER_SIZE);
int nReadFileSize = unzReadCurrentFile(unzfile, szReadBuffer, BUFFER_SIZE);
if(nReadFileSize < ) //读取文件失败
{
MessageBox("读取文件失败!", "提示", MB_OK|MB_ICONWARNING);
unzCloseCurrentFile(unzfile);
CloseHandle(hFile);
return;
}
else if(nReadFileSize == ) //读取文件完毕
{
unzCloseCurrentFile(unzfile);
CloseHandle(hFile);
break;
}
else //写入读取的内容
{
DWORD dWrite = ;
BOOL bWriteSuccessed = WriteFile(hFile, szReadBuffer, BUFFER_SIZE, &dWrite, NULL);
if(!bWriteSuccessed)
{
MessageBox("读取文件失败!", "提示", MB_OK|MB_ICONWARNING);
unzCloseCurrentFile(unzfile);
CloseHandle(hFile);
return;
}
}
}
}
break;
}
unzGoToNextFile(unzfile);
} //关闭
if(unzfile)
{
unzClose(unzfile);
}
}

3.4运行结果

  调用上述的UnzipFile()方法对某个zip文件进行解压,如图1所示。

图1 解压zip文件

  解压后,可以看到文件夹123中的内容如图2所示。

图2 解压后的文件

【VC++技术杂谈008】使用zlib解压zip压缩文件的更多相关文章

  1. C# 解压zip压缩文件

    此方法需要在程序内引用ICSharpCode.SharpZipLib.dll 类库 /// <summary> /// 功能:解压zip格式的文件. /// </summary> ...

  2. [转]Ubuntu Linux 安装 .7z 解压和压缩文件

    [转]Ubuntu Linux 安装 .7z 解压和压缩文件 http://blog.csdn.net/zqlovlg/article/details/8033456 安装方法: sudo apt-g ...

  3. C#利用SharpZipLib解压或压缩文件夹实例操作

    最近要做一个项目涉及到C#中压缩与解压缩的问题的解决方法,大家分享. 这里主要解决文件夹包含文件夹的解压缩问题. )下载SharpZipLib.dll,在http://www.icsharpcode. ...

  4. C# 解压RAR压缩文件

    此方法适用于C盘windows文件夹中有WinRAR.exe文件 /// 解压文件(不带密码) RAR压缩程序 返回解压出来的文件数量 /// </summary> /// <par ...

  5. PHP 的解压缩ZipArchive中的extractTo()方法 LINUX+nginx环境中解压zip时文件丢失的问题

    在项目中要用ZipArchive解压ZIP文件,起初測试环境在WINDOWS平台中,測试通过,换到 LINUX+nginx 的环境中时 就出问题了(ZIP包中有文件和目录一共3百多个文件,大部分是带汉 ...

  6. C#解压或压缩文件夹

    这里主要解决文件夹包含文件夹的解压缩问题.1)下载SharpZipLib.dll,在http://www.icsharpcode.net/OpenSource /SharpZipLib/Downloa ...

  7. linux解压rar压缩文件

    服务器是阿里云的 centos 默认linux是没有安装解压rar,zip的软件的.而网上找到的yum install命令也没有用.而且这个rar并不是免费的,只有40天的试用期...真是坑啊 由于用 ...

  8. [转]Ubuntu Linux 安装 .7z 解压和压缩文件

    原文网址:http://blog.csdn.net/zqlovlg/article/details/8033456 安装方法: sudo apt-get install p7zip-full 解压文件 ...

  9. linux下如何解压和压缩文件

    1.*.tar 用 tar –xvf 解压 2.*.gz 用 gzip -d或者gunzip 解压 3.*.tar.gz和*.tgz 用 tar –xzf 解压 4.*.bz2 用 bzip2 -d或 ...

随机推荐

  1. Python爬虫学习(7):浙大软院网号嗅探

    软院这边网速是挺不错的,而且在宿舍和实验室都是可以通过学号直接登陆的上网的,但是..有的时候实验室的台式机需要一个网号,笔记本需要一个网号,或者再加上一个路由器需要一个,然后,感觉网号托托的不够呀.刚 ...

  2. Python2 新手 编码问题 吐血总结

    什么是编码 任何一种语言.文字.符号等等,计算都是将其以一种类似字典的形式存起来的,比如最早的计算机系统将英文文字转为数字存储(ASCII码),这种文字与数字(或其他)一一对应的关系我们称之为编码.由 ...

  3. 【原】iOS学习之PINCache第三方缓存框架

    在项目中总是需要缓存一些网络请求数据以减轻服务器压力,业内也有许多优秀的开源的解决方案.通常的缓存方案都是由内存缓存和磁盘缓存组成的,内存缓存速度快容量小,磁盘缓存容量大速度慢可持久化. 1.PINC ...

  4. kafka的log存储解析——topic的分区partition分段segment以及索引等

    转自:http://blog.csdn.net/jewes/article/details/42970799 引言 Kafka中的Message是以topic为基本单位组织的,不同的topic之间是相 ...

  5. SVN出现Invalid authz configuration解决方案

    思路: 1.检查是否为不存在的用户组或用户设置了权限(大部分为此问题,调整用户权限或删除账号后,但忘了去掉某个文件夹的权限) 2.检查authz文件的编码: 3.更改权限后是否未重启svn. 4.按照 ...

  6. IntelliJ IDEA - 热部署插件JRebel 安装使用教程

    IntelliJ IDEA - JRebel 安装使用教程 JRebel 能做什么? JRebel 是一款热部署插件.当你的 Java-web 项目在 tomcat 中 run/debug 的时候 , ...

  7. redis 的理解

    1.Redis使用 C语言开发的.Redis 约定此版本号,为偶数的版本是稳定版(如:2.4版 2.6版),奇数版是非稳定版(如:2.5版 2.7版) 2.Redis 数据库中的所有的数据都存储在内存 ...

  8. linux终端 字符界面 显示乱码

    方法一:配置SSH工具 SecureCRT中文版配置 [全局选项]→[默认会话]→[编辑默认设置]→[终端]→[外观]→[字体]→[新宋体 10pt CHINESE_GB2312]→[字符编码 UTF ...

  9. pip安装MySQL-python报错

    pip install MySQL-pythonerror: command 'gcc' failed with exit status 1 yum install -y python-develpi ...

  10. Oracle中的CHR()函数与ASCII()函数

    工作中经常会处理一些因特殊字符而导致的错误,如上周我就遇到了因为换行符和回车符导致的数据上报的错误,这种错误比较难以发现,通常是由于用户的输入习惯导致的,有可能数据极少,就那么几行错误从而导致整个数据 ...