随记~关于zlib库的使用

这星期在做一个换肤的模块,类似芊芊静听,原文件是一个zip文件,所以要将文件解压缩到文件夹中。

       解压的方法大致有3种:

       1. 通过shellexcute执行rar.exe等外部程序。

       2. 使用第三方类库。

       3. 直接手写。

       因为我们不能假设每个用户机器都必备类似rar.exe这种外部程序(虽然该软件已成装机必备),个人认为第一种方法很不靠谱。而本人能力有限,第三种方法也排除。于是选用第三方库。

       选用的第三方库是很出名的zlib,官方网站为 www.zlib.net。

       zlib提供了两个很傻瓜的接口:

 

       int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,

                                                   const Bytef *source, uLong sourceLen));

       int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,

                                                       const Bytef *source, uLong sourceLen));

 

       类似的还有:

 

       int ZEXPORT deflate OF((z_streamp strm, int flush));

       int ZEXPORT inflate OF((z_streamp strm, int flush));

 

       但这样的接口只能将字符压缩/解压缩为字符。

       zlib还提供了对zip文件的读写函数:

 

       gzFile ZEXPORT gzopen  OF((const char *path, const char *mode));

       int ZEXPORT    gzread  OF((gzFile file, voidp buf, unsigned len));

       int ZEXPORT    gzwrite OF((gzFile file, voidpc buf, unsigned len));

 

       使用这三个接口之前,先来了解下zip文件格式 。

       ZIP文件格式分为三部分:压缩源文件数据区+压缩源文件目录区+压缩源文件目录结束标志。

       每部分都有各自的数据格式。如文件头, 文件数据, 数据描述符等乱七八糟的东西。而gzread读出来的正是zip文件的全部数据。包括头文件等。

       我所要解压的文件中包含多个位图,所以直接对gzread读取出的字符进行操作是不实际的。

       解决方法是去掉字符中不属于数据源的部分,只提取数据源。


操作方法如下:

       在zlib的contrib文件夹中有个minizip的例子,与其说是例子,不如说是zlib提供的更高层的接口。

       我使用的函数大致在4个文件中:unzip.h, unzip.c, zip.h, zip.c 。

压缩相关:

 

       zipOpen64

       zipClose

       zipOpenNewFileInZip

       zipCloseFileInZip

       zipWriteInFileInZip 

 

解压相关:

 

       unzOpen64

       unzClose

       unzGetGlobalInfo64

       unzGoToFirstFile

       unzGoToNextFile

       unzGetCurrentFileInfo64

       unzOpenCurrentFile

       unzCloseCurrentFile

       unzReadCurrentFile

 

      从名字就可以理解这些函数的妙用。捎做一提的是,除了zipopen64和unzopen64参数为char*的字符串,用作路径,其他的函数都以unzFile为参数类型,unzFile等同于void*, 但是传递的是一个结构体,用于存放文件的不同数据。由于做的是解压,下面只讲下解压的方法,压缩的方法大同小异。

具体操作如下:

      unzOpen64打开zip文件,在函数内部会生成一个unz64_s的结构体,这个结构体是使用所有函数的关键。然后在open中使用unzGoToFirstFile((unzFile)s)可以得到zip文件中第一个文件的数据。接着调用unzOpenCurrentFile((unzFile)s),unzReadCurrentFile((unzFile)s, buf, UNZ_BUFSIZE), 就可以读取文件中的数据了,这个数据就是我需要的原数据了,unz64local_GetCurrentFileInfoInternal((unzFile)s, &s->cur_file_info,&s->cur_file_info_internal, name,100,NULL,0,NULL,0);可以得到文件的名字,在这里就是xxx.bmp,然后通过fwrite写入数据。这样 ,一个文件就是解压出来了。然后调用unzGoToNextFile((unzFile)s)可以得到zip文件中下一个的数据文件。遍历完所有的文件后,可以通过 unzClose((unzFile)s)关闭zip文件。

     一个需要注意的地方是调用unzReadCurrentFile时会传递一个需要传递到的内存的长度 ,如果这个数值太小的话,是得不到全部数据的。


后记

     这篇文章并没有什么技术性,纯粹是记录了对zlib的简单使用,留有后用。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页