mfc zlib minizip vs2019

网友投稿 1181 2022-10-14

mfc zlib minizip vs2019

mfc zlib minizip vs2019

需要注意Release和Debug使用的dll可能有差异,Release时需要使用对应的Dll

zlib源码文件中zlib123\contrib\vstudio此文件夹包含所需的zip、unzip相关实例代码minizip 最新版为zlib1.2.11

相关库文件导入zlib.h,zconf.h

include "zlib.h"

include "zconf.h"

pragma comment(lib,"zlib.lib")

LNK2001: 默认调用规则不一致,添加预定义即可

define ZLIB_WINAPI

LNK4098: defaultlib "libc.lib" conflicts with use of other libs; use /NODEFAULTLIB:library 项目->属性中->配置属性->链接器->输入->在忽略特定库中写入打不开的文件的名称libc.lib

D8016: 项目”—>“属性”—>“C/C++” “常规”—>“调试信息格式”—>选择“程序数据库(/Zi)”或“无” 项目”—>“属性”—>“C/C++” 代码生成”—>“启用函数集链接”—>选择“是 (/Gy)”

LNK1104无法打开libc.lib “项目”-->“配置属性->链接器->输入->忽略特定库”后填入“LIBC.lib ”。

LNK1281 无法生成 SAFESEH 映像 “项目”-->“配置属性->链接器-命令行 输入 /SAFESEH:NO

1>unzip.obj : error LNK2019: 无法解析的外部符号_inflateInit2_,该符号在函数_unzOpenCurrentFile3 中被引用

1>unzip.obj : error LNK2019: 无法解析的外部符号_inflate,该符号在函数_unzReadCurrentFile 中被引用

1>unzip.obj : error LNK2019: 无法解析的外部符号_crc32,该符号在函数_unzReadCurrentFile 中被引用

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

1>unzip.obj : error LNK2019: 无法解析的外部符号_inflateEnd,该符号在函数_unzCloseCurrentFile 中被引用

1>zip.obj : error LNK2019: 无法解析的外部符号_get_crc_table,该符号在函数_zipOpenNewFileInZip4_64 中被引用

1>zip.obj : error LNK2019: 无法解析的外部符号_deflateInit2_,该符号在函数_zipOpenNewFileInZip4_64 中被引用

1>zip.obj : error LNK2019: 无法解析的外部符号_deflate,该符号在函数_zipWriteInFileInZip 中被引用

1>zip.obj : error LNK2019: 无法解析的外部符号_deflateEnd,该符号在函数_zipCloseFileInZipRaw64 中被引用

zconf.h

# define ZEXPORT WINAPI 替换为 #define ZEXPORT __cdecl#define ZEXPORTVA WINAPIV 替换为 #define WINAPIV __cdecl

解压缩时在inffas32.asm中报错的处理方式&编译时会提示inflate_fast重复定义

1. 在zlib源码的zlibvc工程属性-预处理器定义里面去掉 ASMINF、ASMV 定义,屏蔽掉汇编模块2. 打开zlib-1.2.11\contrib\masmx86下面的汇编文件inffas32.asm,将里面_inflate_fast全部替换成其他任意函数名

zip相关实现

zip解压缩

将zlib-1.x.x\contrib\minizip文件夹下除miniunz.c和minizip.c以外的.h与.c文件放到项目目录下,并将zip.h与unzip.h导入到工程中。打开需要解压缩的文件

//传入zip文件的绝对路径,返回一个unzFile对象。这是一个void*指针,用于指向打开的zip文件unzFile unzOpen(const char *path);

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

int unzClose OF(unzFile file);

获取zip文件的信息

int unzGetGlobalInfo(unzFile file, unz_global_info *pglobal_info);

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

传入的unz_global_info定义如下:

//注意number_entry的值是zip文件中的文件盒文件夹总数。与是否嵌套无关。//例如://将3个文件打包成一个zip,那么获取到的该值就是3;//一个文件夹A,含有2个文件以及一个子文件夹B;B中含有1个文件。直接对A进行打包,那么调用该函数获取到的值是5。这是因为这个压缩包中,共含有2个文件//夹和3个文件,总数为5。typedef struct unz_global_info_s{ uLong number_entry; // zip文件中的文件和文件夹总数 uLong size_comment; // zip文件的注释所占大小} unz_global_info;

返回值

#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)

对于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 bytes uLong version_needed; // 解压文件所需pkware版本 2 bytes uLong flag; // 全局方式位标记 2 bytes uLong compression_method; // 压缩方式 2 bytes uLong dosDate; // 文件最后修改日期时间 4 bytes uLong crc; // CRC-32校验 4 bytes uLong compressed_size; // 压缩后大小 4 bytes uLong uncompressed_size; // 未压缩大小 4 bytes uLong size_filename; // 文件名长度 2 bytes uLong size_file_extra; // 文件扩展字段长度 2 bytes uLong size_file_comment; // 文件注释长度 2 bytes uLong disk_num_start; // 磁盘开始号 2 bytes uLong internal_fa; // 内部文件属性 2 bytes uLong external_fa; // 外部文件属性 4 bytes tm_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,则认为是个文件。

对于已经定位到的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; }}

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

int unzGoToNextFile(unzFile file);

然后重复步骤上面的几个步骤

若成功,则return UNZ_OK

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

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

int unzClose(unzFile file);

对于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

对于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指针中的信息,将当前文件定位到指定文件。

获取zip文件的注释:

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

封装后的代码

​​UZip​​

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Kohana- PHP 5 框架
下一篇:TR0217- 插件框架
相关文章

 发表评论

暂时没有评论,来抢沙发吧~