轉載: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; }