将zconf.h,zlib.h,zlibwapi.dll,zlibwapi.lib这4个文件放到项目目录下,并将头文件导入到工程中。

将zlib-1.2.8\contrib\minizip文件夹下除miniunz.c和minizip.c以外的.h与.c文件放到项目目录下,并将zip.h与unzip.h导入到工程中。

这样,就可以使用zip.h和unzip.h中的函数操作zip压缩包了。

其中:

zip.h负责压缩操作。

unzip.h负责解压缩操作。

注意:由于解压缩带密码的zip文件的功能被默认屏蔽,所以若要开启此功能,需要将unzip.c文件中的

#ifndef NOUNCRYPT
#define NOUNCRYPT
#endif

改为:

#ifndef NOUNCRYPT
//        #define NOUNCRYPT
#endif

这是因为在unzip.c的unzOpenCurrentFile3函数中:

extern int ZEXPORT unzOpenCurrentFile3(unzFile file, int* method, int* level, int raw, const char* password)
{……
#    ifndef NOUNCRYPTchar source[12];
#    elseif (password != NULL)return UNZ_PARAMERROR;
#    endif……
}

若NOUNCRYPT宏被定义,则当password!=NULL时,会直接返回UNZ_PARAMERROR。

修改了unzip.c文件后,zlibwapi.lib与zlibwapi.dll文件需要重新生成。

解压缩

对于一个zip文件,内部可能有个文件夹嵌套,每个文件夹下都可能存在文件。

故读取zip文件,首先要对zip文件的信息进行获取,查看其内部有多少个文件,注释占多大空间。

初始状态下,会自动定位在第一个文件或文件夹。每处理完一个文件或文件夹,调用函数跳转到下一个文件或文件夹,直到所有文件或文件夹处理完毕。因此这需要一个for或者while循环。

对于每个文件或文件夹,都可以用函数来获取其文件名。因为可能会嵌套,故其文件名是包含相对路径的。若文件名以”/”结尾,则表明这是个文件夹。

实际上,所谓解压,就是将压缩包的数据读出来,然后写到另一个文件中。但另一个文件zlib库并不会为我们生成,故需要自己创建。也就是说,读出的第一个文件是文件夹,那么就要创建一个同名文件夹;读出的第二个文件是位于该文件夹下的一个png文件,那么就要在该文件夹下创建一个与png同名的文件,然后将解压出的数据写入。

其用到的函数如下:

1.    打开需要解压缩的文件:

unzFile unzOpen(const char *path);

传入zip文件的绝对路径,执行该函数会返回一个unzFile对象。这是一个void*指针,用于指向打开的zip文件。

后续的各种操作都要使用该unzFile对象。

对应地,操作完毕后需要关闭已打开的压缩文件:

int unzClose OF(unzFile file);

2.    获取zip文件的信息

int unzGetGlobalInfo(unzFile file, unz_global_info *pglobal_info);

传入通过1获取到的unzFile对象,传入一个空的unz_global_info*,函数执行完成后,会将zip文件的信息填充到该unz_global_info*指针中。

①   传入的unz_global_info定义如下:

typedef struct unz_global_info_s
{uLong number_entry;         // zip文件中的文件和文件夹总数uLong size_comment;         // zip文件的注释所占大小
} unz_global_info;

注意number_entry的值是zip文件中的文件盒文件夹总数。与是否嵌套无关。

例如:

将3个文件打包成一个zip,那么获取到的该值就是3;

一个文件夹A,含有2个文件以及一个子文件夹B;B中含有1个文件。直接对A进行打包,那么调用该函数获取到的值是5。这是因为这个压缩包中,共含有2个文件夹和3个文件,总数为5。

②   返回值为执行的结果信息。有以下取值:

#define UNZ_OK                          (0)
#define UNZ_END_OF_LIST_OF_FILE         (-100)
#define UNZ_ERRNO                       (Z_ERRNO)
#define UNZ_EOF                         (0)
#define UNZ_PARAMERROR                  (-102)
#define UNZ_BADZIPFILE                  (-103)
#define UNZ_INTERNALERROR               (-104)
#define UNZ_CRCERROR                    (-105)

3.    对于zip文件中定位的当前文件,可以通过函数来获取其信息:

int unzGetCurrentFileInfo(   unzFile file,unz_file_info *pfile_info,char *szFileName,uLong fileNameBufferSize,void *extraField,uLong extraFieldBufferSize,char *szComment,uLong commentBufferSize);

关于其参数:

①   unzFile file:已打开的unzFile对象

②   unz_file_info *pfile_info:一个头文件信息对象的指针,传入后,函数会将当前文件的信息填充到该指针指向的对象中。详见下面说明

③   char *szFileName:用于保存文件名,需在外部new出足够大的存储空间,函数会将文件的路径+文件名保存在该对象中。注意该文件名的路径是个相对路径,其最顶层为被压缩的最上层文件或文件夹

④   uLong fileNameBufferSize:与③统一,告知函数new了多大的char*内存

⑤   void* extraField:用于保存扩展内容,需在外部new出足够大的存储空间,函数会将文件的扩展内容保存在该对象中

⑥   uLong extraFieldBufferSize:与⑤统一,告知函数new了多大的内存

⑦   char* szComment:用于保存注释内容,需在外部new出足够大的存储空间,函数会将文件的注释内容保存在该对象中

⑧   uLong commentBufferSize:与⑦统一,告知函数new了多大的内存

对于其中的unz_file_info结构体,定义如下:

typedef struct unz_file_info_s
{uLong version;              // 压缩文件所使用的pkware版本    2 bytesuLong version_needed;       // 解压文件所需pkware版本        2 bytesuLong flag;                 // 全局方式位标记               2 bytesuLong compression_method;   // 压缩方式                  2 bytesuLong dosDate;              // 文件最后修改日期时间            4 bytesuLong crc;                  // CRC-32校验                  4 bytesuLong compressed_size;      // 压缩后大小                 4 bytesuLong uncompressed_size;    // 未压缩大小                 4 bytesuLong size_filename;        // 文件名长度                 2 bytesuLong size_file_extra;      // 文件扩展字段长度              2 bytesuLong size_file_comment;    // 文件注释长度                    2 bytesuLong disk_num_start;       // 磁盘开始号                 2 bytesuLong internal_fa;          // 内部文件属性                    2 bytesuLong external_fa;          // 外部文件属性                    4 bytestm_unz tmu_date;            // 文件创建日期
} unz_file_info;

实际上,一般的zip文件很少使用扩展与注释。对于没有扩展与注释的,参数⑤⑦可以传入null,参数⑥⑧可以传入0。

注意获取到的文件名。若该文件名以路径分隔符”/”结尾,表明这是个文件夹;否则表明这是个文件。

判断一个文件名是文件还是文件夹,还可以利用external_fa字段。该字段的值会被填充为winnt.h中的FILE宏定义。通常,若external_fa  = 16,即0x00000010,则说明是个文件夹;若external_fa   = 32,即0x00000020,则说明是个文件。

在winnt.h中:

#define FILE_ATTRIBUTE_DIRECTORY            0x00000010
#define FILE_ATTRIBUTE_ARCHIVE              0x00000020  

一般来说,在这里若external_fa !=FILE_ATTRIBUTE_DIRECTORY,则认为是个文件。

4.    对于已经定位到的zip中的单个文件,就可以执行解压缩了。解压缩过程如下:

①   打开该定位到的文件:

int unzOpenCurrentFile(unzFile file);

返回值为执行的结果信息。

对于加密的文件,需要传入密码:

int unzOpenCurrentFilePassword(unzFile file, const char* password);

若返回值不为UNZ_OK,则解压出错,可以根据返回值判断是文件本身问题还是解压问题。

②   读取文件内容:

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

传入unzFile对象,创建一个缓冲区用于存放读取的内容,将缓冲区指针和大小传入。

由于缓冲区并不一定足够大,所以需要进行多次读取。每次读取,当前的读取位置都会被修改。

例如,一个文件读取需要10M空间。创建了一个1M大小的缓冲区。第一次调用该函数读取,当前位置指向文件的开始,读了1M大小的数据,将该数据存入缓冲区中;第二继续调用该函数来读取,此时当前位置由于第一次的读取,已经指向了1M数据结尾的地方,所以第二次读取会从1M结尾开始,读取1M大小的数据……调用该函数10次,即可读取完所有的数据。

文件的读取状况,是依靠返回值来判定的:

return>0:正常读取了文件的一部分内容,返回值为读取的字节数

return==0:没有数据被读取,说明文件已经读取完毕

return<0:读取出错,返回错误码

③   将缓冲区内容写入到创建的文件中:

这需要借助操作系统的函数来进行。同样是要对一个文件进行多次写入。

示例代码:

const int BUFFER_SIZE = 4096;
char szReadBuffer[BUFFER_SIZE];
while (TRUE)
{memset(szReadBuffer, 0, BUFFER_SIZE);  //清理缓冲区int nReadFileSize = unzReadCurrentFile(unzfile, szReadBuffer, BUFFER_SIZE); //读取int result;if (nReadFileSize > 0)    result = 1;    //读取文件部分数据if (nReadFileSize == 0) result = 0;    //读取文件结束if (nReadFileSize < 0)   result = -1;   //读取文件失败switch (result){case 1:{//读取文件部分数据//将其写入到创建的文件中}break;case 0:{//读取文件结束unzCloseCurrentFile(unzfile);return;}break;case -1:{//读取文件失败unzCloseCurrentFile(unzfile);}break;}
}

5.    当前文件解析完毕,则跳转到下一个文件:

int unzGoToNextFile(unzFile file);

然后重复步骤3,4。

若成功,则return UNZ_OK

若失败,说明已到文件尾,则return UNZ_END_OF_LIST_OF_FILE

6.    对zip文件解压缩完毕后,要将文件关闭:

int unzClose(unzFile file);

7.    对于zip中各个文件和文件夹的定位,可以使用以下函数:

int unzGoToFirstFile(unzFile file);
int unzGoToNextFile(unzFile file);
int unzLocateFile(unzFile file, const char *szFileName, int iCaseSensitivity);

关于iCaseSensitivity参数:

iCaseSensitivity = 1,则文件名的匹配区分大小写。

iCaseSensitivity = 2,则文件名的匹配不区分大小写。

iCaseSensitivity = 0,则文件名的匹配按操作系统自行决定。Unix使用1,Windows使用2

8.    对于zip中各个文件和文件夹的位置,可以使用索引:

typedef struct unz_file_pos_s
{uLong pos_in_zip_directory;   // 文件在zip文件中的偏移uLong num_of_file;            // 在文件中的索引
} unz_file_pos;int unzGetFilePos(unzFile file, unz_file_pos* file_pos);
int unzGoToFilePos(unzFile file, unz_file_pos* file_pos);

unzGetFilePos函数会将当前定位文件的信息填入传入的unz_file_pos指针中。

unzGoToFilePos函数会根据传入的unz_file_pos指针中的信息,将当前文件定位到指定文件。

9.    获取zip文件的注释:

int unzGetGlobalComment(unzFile file, char *szComment, uLong uSizeBuf);

传入定义的缓存区首地址及其大小。

zlib解压缩zip相关推荐

  1. 封装基于zlib的minizip库用于解压缩zip文件

    开发中需要用到解压缩.zip文件的功能,查阅资料后尝试使用开源库zlib中提供的的minizip源码,这篇文章记录具体的调用实现和学习过程,方便后续问题发现和补充. 跨平台环境:C/C++ / Win ...

  2. PclZip:强大的PHP压缩与解压缩zip类

    PclZip介绍 PclZip library能够压缩与解压缩Zip格式的压缩档(WinZip.PKZIP):且能对此类类档案进行处理,包括产生压缩档.列出压缩档的内容以及解压 缩档案等等.由于能够在 ...

  3. 用C实现解压缩ZIP文件到内存

    ZIP文件格式是非常常用的一种压缩格式,比如M$新的EXCEL文件格式其实就是一个ZIP压缩文件,压缩文件内部是几个带路径的XML文件.如果我们想解析EXCEL文件的内容就要把压缩文件内的XML文件先 ...

  4. Ubuntu解压缩zip,tar,tar.gz,tar.bz2

    Ubuntu解压缩zip,tar,tar.gz,tar.bz2 ZIP zip可能是目前使用得最多的文档压缩格式.它最大的优点就是在不同的操作系统平台,比如Linux, Windows以及Mac OS ...

  5. ubuntu解压缩zip/tar/tar.gz/tar.bz2

    ubuntu解压缩zip/tar/tar.gz/tar.bz2 ZIP zip可能是目前使用得最多的文档压缩格式.它最大的优点就是在不同的操作系统平台,比如Linux, Windows以及Mac OS ...

  6. java压缩/解压缩zip格式文件

    因为项目要用到压缩.解压缩zip格式压缩包,只好自己封装一个,对于网上流行的中文乱码的问题,本文的解决方法是用apache的包代替jdk里的.基本上还是比较好用的. 废话少说,直接上代码. 1 pac ...

  7. 宝塔linux上传文件视频,使用宝塔linux面板上传文件 解压缩zip和tar.gz

    塔面板是国内一款免费linux和windows面板,如下面小斌就来解答一下.何使用宝塔linux面板上传文件,宝塔linux如何解压上传的文件. 首先我们登陆宝塔linux面板的管理后台,还没有安装的 ...

  8. 解压缩zip文件的工具类

    此方法可以直接解压缩zip中的文件及文件夹至指定目录,zip中文件名称不能包含繁体字符. import java.io.*; import java.util.ArrayList; import ja ...

  9. oracle两个压缩包怎么解压,AIX下如何解压缩zip文件

    1.首先检查是否安装如下包,若没有安装的话需要从安装介质中安装 lslpp -l |grep -i rpm.rte lslpp -l |grep -i rpm.rte就可以像linux那样使用rpm命 ...

最新文章

  1. 独家 | 数据科学家对可复用Python代码的实用管理方法(附链接)
  2. autoconfig oracle,ORACLE EBS 执行autoconfig time out
  3. kafka生产者、消费者消息操作命令
  4. SharePoint designer 文件--新建中没有工作流
  5. vue-i18n使用及踩坑记录
  6. Cocos2d-x 3.x如何通过WebSocket连接服务器进行数据传输
  7. linux 指定cpu运行线程,linux 线程与CPU绑定
  8. matplotlib数据可视化实战——饼状图+雷达图+三维图
  9. 算法笔记_面试题_2.移动零(将数组的的0元素移到末尾)
  10. matlab小波具体频段,一种小波包分解节点与对应频段检索及编程方法
  11. Windows下Xelatex的使用
  12. 如何将nideshop部署到本地
  13. GD32F103RBT6开发笔记
  14. Spring cloud oauth2搭建OAuth2.0授权服务
  15. Error creating bean with name ‘serverEndpointExporter‘ defined in class path resource
  16. 计算机中完成全选的快捷键,怎么全选-很实用!word中全选的快捷键介绍及使用方法...
  17. 不能换行 俄语 前端h5_H5兼容问题及解决方法
  18. DigitalPersona Personal 4 x86 下载
  19. OpenCV+C++ 查找文件中的图片,处理后保存
  20. 关于冒险岛封包拦截程序的开发计划

热门文章

  1. 堪比病毒营销的新思路:换个姿势玩抖音!
  2. WOFOST模型Matlab,一种WOFOST-PAR耦合模型建立方法与流程
  3. 1*1卷积核的作用(bottleneck的作用)
  4. 系统集成项目管理工程师笔记(2)信息系统服务管理
  5. 某程序员感叹:4年开发,年包才40多万
  6. Spark伪分布式搭建与SparkYarn搭建
  7. asp.net 页面清除缓存
  8. Numpy+Pandas+Matplotlib学习
  9. c语言数组求欧几里得距离,计算scipy-csr矩阵中的欧氏距离
  10. 第二证券|医药板块短期轮动加快 机构看好后市机会