minizip -基于zlib开源代码库
转载:https://www.topomel.com/archives/979.html
一、minizip
是一套用来压缩和解压文件的工具,其基于zlib开源代码库。
开源代码下载链接:http://www.winimage.com/zLibDll/minizip.html
二、压缩文件
使用minizip压缩文件,我们一般使用如下的几个函数:
zipOpen2_64:新建一个空的Zip文件
zipOpenNewFileInZip3_64:添加一个文件到之前创建好的Zip文件中
zipWriteInFileInZip:读取文件内容并写入到Zip文件
zipCloseFileInZip:关闭当前Zip文件
zipClose: 关闭Zip文件
这里有几个地方需要注意:
1) 在调用zipOpenNewFileInZip3_64在Zip文件中添加文件之前,我们需要计算文件的CRC效验码和文件的时间戳信息,否则,会出现生成的Zip文件解压时头部错误的问题。
2) 读取文件并写入Zip文件过程中,我们需要使用循环的方式,每次对文件读取一定的字节,并注意检查是否到达文件尾(EOF),同时需要检查zipWriteInFileInZip调用是否失败。
伪代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
新建Zip文件(zipOpen2_64) 获取源文件时间戳信息(filetime) 在Zip中创建新文件(zipOpenNewFileInZip3_64) 打开源文件( fopen ) do { 读取源文件一定字节( fread ) 写入到Zip文件(zipWriteInFileInZip) } while (源文件未到达EOF) 关闭源文件( fclose ) 关闭Zip当前文件(zipCloseFileInZip) 关闭Zip文件(zipClose) |
解压Zip文件
在解压一个Zip文件时,我们需要使用的函数如下:
unzOpen64:打开Zip文件
unzGetGlobalInfo64:获取Zip文件的全局信息
unzGetCurrentFileInfo64:获取当前文件信息
unzOpenCurrentFile:打开Zip中的文件
unzReadCurrentFile:读取文件内容
unzCloseCurrentFile:关闭当前文件
unzGoToNextFile:准备读取Zip文件中的下一个文件
unzClose:关闭Zip文件
伪代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
打开Zip文件(unzOpen64) 获取全局信息(unzGetGlobalInfo64) for (从全局信息中获取所有Zip文件并遍历) 获取当前文件信息(unzGetCurrentFileInfo64) if (当前Zip文件是目录) 创建目录 else 打开Zip文件(unzOpenCurrentFile) 打开目标文件( fopen ) while (Zip文件读取成功) 读取Zip文件(unzReadCurrentFile) 写入目标文件( fwrite ) 关闭目标文件( fclose ) 关闭当前Zip文件(unzCloseCurrentFile) 准备处理下一个Zip文件(unzGoToNextFile) 关闭Zip文件(unzClose) |
代码例子:
#include <stdio.h> #include <string.h> #include "unzip.h" #define dir_delimter '/' #define MAX_FILENAME 512 #define READ_SIZE 8192 int main( int argc, char **argv ) { if ( argc < 2 ) { printf( "usage:\n%s {file to unzip}\n", argv[ 0 ] ); return -1; } // Open the zip file unzFile *zipfile = unzOpen( argv[ 1 ] ); if ( zipfile == NULL ) { printf( "%s: not found\n" ); return -1; } // Get info about the zip file unz_global_info global_info; if ( unzGetGlobalInfo( zipfile, &global_info ) != UNZ_OK ) { printf( "could not read file global info\n" ); unzClose( zipfile ); return -1; } // Buffer to hold data read from the zip file. char read_buffer[ READ_SIZE ]; // Loop to extract all files uLong i; for ( i = 0; i < global_info.number_entry; ++i ) { // Get info about current file. unz_file_info file_info; char filename[ MAX_FILENAME ]; if ( unzGetCurrentFileInfo( zipfile, &file_info, filename, MAX_FILENAME, NULL, 0, NULL, 0 ) != UNZ_OK ) { printf( "could not read file info\n" ); unzClose( zipfile ); return -1; } // Check if this entry is a directory or file. const size_t filename_length = strlen( filename ); if ( filename[ filename_length-1 ] == dir_delimter ) { // Entry is a directory, so create it. printf( "dir:%s\n", filename ); mkdir( filename ); } else { // Entry is a file, so extract it. printf( "file:%s\n", filename ); if ( unzOpenCurrentFile( zipfile ) != UNZ_OK ) { printf( "could not open file\n" ); unzClose( zipfile ); return -1; } // Open a file to write out the data. FILE *out = fopen( filename, "wb" ); if ( out == NULL ) { printf( "could not open destination file\n" ); unzCloseCurrentFile( zipfile ); unzClose( zipfile ); return -1; } int error = UNZ_OK; do { error = unzReadCurrentFile( zipfile, read_buffer, READ_SIZE ); if ( error < 0 ) { printf( "error %d\n", error ); unzCloseCurrentFile( zipfile ); unzClose( zipfile ); return -1; } // Write data to file. if ( error > 0 ) { fwrite( read_buffer, error, 1, out ); // You should check return of fwrite... } } while ( error > 0 ); fclose( out ); } unzCloseCurrentFile( zipfile ); // Go the the next entry listed in the zip file. if ( ( i+1 ) < global_info.number_entry ) { if ( unzGoToNextFile( zipfile ) != UNZ_OK ) { printf( "cound not read next file\n" ); unzClose( zipfile ); return -1; } } } unzClose( zipfile ); return 0; }