根据minizip改写的模块,需要zlib支持

输出的接口:

 1 #define RG_ZIP_FILE_REPLACE    0
 2 #define RG_ZIP_FILE_APPEND            1
 3 
 4 //压缩文件夹目录,递归压缩
 5 //szDir是需要压缩的目录,dstLevel是压缩的目录在压缩包里面的层次标识
 6 //可直接指定""
 7 //szZipFile压缩包的文件名
 8 //replaceFlag指定替换或者是追加进压缩包
 9 int DoZipDir(const char* szDir, const char* dstLevel, const char* szZipFile, int replaceFlag);
10 
11 //压缩单个文件,szFile是文件名,其它参数解析同上
12 int DoZipFile(const char* szFile, const char* dstLevel, const char* szZipFile, int replaceFlag);
13 
14 //解压缩文件
15 //szZipFile是需要解压的压缩包文件名
16 //指定需要解压到的目录,直接指定为"",解压至当前目录
17 int DoUnzip(const char* szZipFile, const char* szTargetDir);
18 
19 //从压缩包里面解压单个文件出来
20 //srcFileToExtract对应压缩文件时的dstLevel
21 //其它参数解析同上
22 int DoUnzipFile(const char* szZipFile, const char* srcFileToExtract, const char* szTargetDir);  

本文仅仅提供封装的api,zlib库和info-zip请自行下载

其它涉及的代码可以下载minizip或者info-zip,推荐使用minizip,本代码是在minizip的基础上修改而来,支持跨平台

  1 /*
  2 minizip.c
  3 Version 1.1, February 14h, 2010
  4 sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
  5 
  6 Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
  7 
  8 Modifications of Unzip for Zip64
  9 Copyright (C) 2007-2008 Even Rouault
 10 
 11 Modifications for Zip64 support on both zip and unzip
 12 Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
 13 */
 14 
 15 #ifdef _DEBUG
 16 #pragma comment(lib, "../../lib/win32/libzd.lib")
 17 #else
 18 #pragma comment(lib, "../../lib/win32/libz.lib")
 19 #endif
 20 
 21 #ifndef _WIN32
 22 #ifndef __USE_FILE_OFFSET64
 23 #define __USE_FILE_OFFSET64
 24 #endif
 25 #ifndef __USE_LARGEFILE64
 26 #define __USE_LARGEFILE64
 27 #endif
 28 #ifndef _LARGEFILE64_SOURCE
 29 #define _LARGEFILE64_SOURCE
 30 #endif
 31 #ifndef _FILE_OFFSET_BIT
 32 #define _FILE_OFFSET_BIT 64
 33 #endif
 34 #endif
 35 
 36 #include <stdio.h>
 37 #include <stdlib.h>
 38 #include <string.h>
 39 #include <time.h>
 40 #include <errno.h>
 41 #include <fcntl.h>
 42 
 43 #ifdef _LINUX
 44 # include <utime.h>
 45 # include <sys/types.h>
 46 # include <sys/stat.h>
 47 # include <unistd.h>
 48 #include <dirent.h>
 49 #else
 50 # include <direct.h>
 51 # include <io.h>
 52 #endif
 53 
 54 #include "zip.h"
 55 #include "stdstring.h"
 56 #include <vector>
 57 #include "comfun.h"
 58 
 59 using namespace std;
 60 
 61 // #ifdef _WIN32
 62 // #define USEWIN32IOAPI
 63 // #include "iowin32.h"
 64 // #endif
 65 
 66 
 67 
 68 #define WRITEBUFFERSIZE (16384)
 69 #define MAXFILENAME (256)
 70 
 71 #ifdef _WIN32
 72 static uLong filetime(const char *f, tm_zip *tmzip, uLong *dt)
 73 /*char *f;                 name of file to get info on */
 74  /* tm_zip *tmzip;            return value: access, modific. and creation times */
 75  /*uLong *dt;             dostime */
 76 {
 77     int ret = 0;
 78     {
 79         FILETIME ftLocal;
 80         HANDLE hFind;
 81         WIN32_FIND_DATAA ff32;
 82 
 83         hFind = FindFirstFileA(f,&ff32);
 84         if (hFind != INVALID_HANDLE_VALUE)
 85         {
 86             FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
 87             FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
 88             FindClose(hFind);
 89             ret = 1;
 90         }
 91     }
 92     return ret;
 93 }
 94 #else
 95 #ifdef _LINUX
 96 static uLong filetime(const char *f, tm_zip *tmzip, uLong *dt)
 97  /*char *f;               name of file to get info on */
 98 /*tm_zip *tmzip;          return value: access, modific. and creation times */
 99 /*uLong *dt;              dostime */
100 {
101     int ret=0;
102     struct stat s;        /* results of stat() */
103     struct tm* filedate;
104     time_t tm_t=0;
105 
106     if (strcmp(f,"-")!=0)
107     {
108         char name[MAXFILENAME+1];
109         int len = strlen(f);
110         if (len > MAXFILENAME)
111             len = MAXFILENAME;
112 
113         strncpy(name, f,MAXFILENAME-1);
114         /* strncpy doesnt append the trailing NULL, of the string is too long. */
115         name[ MAXFILENAME ] = '\0';
116 
117         if (name[len - 1] == '/')
118             name[len - 1] = '\0';
119         /* not all systems allow stat'ing a file with / appended */
120         if (stat(name,&s)==0)
121         {
122             tm_t = s.st_mtime;
123             ret = 1;
124         }
125     }
126     filedate = localtime(&tm_t);
127 
128     tmzip->tm_sec  = filedate->tm_sec;
129     tmzip->tm_min  = filedate->tm_min;
130     tmzip->tm_hour = filedate->tm_hour;
131     tmzip->tm_mday = filedate->tm_mday;
132     tmzip->tm_mon  = filedate->tm_mon ;
133     tmzip->tm_year = filedate->tm_year;
134 
135     return ret;
136 }
137 #else
138 uLong filetime(char *f, tm_zip *tmzip, uLong *dt)
139 {
140     return 0;
141 }
142 #endif
143 #endif
144 
145 static int check_exist_file(const char* filename)
146 {
147     FILE* ftestexist;
148     int ret = 1;
149     ftestexist = fopen64(filename,"rb");
150     if (ftestexist==NULL)
151         ret = 0;
152     else
153         fclose(ftestexist);
154 
155     return ret;
156 }
157 
158 static int isLargeFile(const char* filename)
159 {
160     int largeFile = 0;
161     ZPOS64_T pos = 0;
162     FILE* pFile = fopen64(filename, "rb");
163 
164     if(pFile != NULL)
165     {
166         int n = fseeko64(pFile, 0, SEEK_END);
167 
168         pos = ftello64(pFile);
169 
170         if(pos >= 0xffffffff)
171             largeFile = 1;
172 
173         fclose(pFile);
174     }
175 
176     return largeFile;
177 }
178 
179 static int DoZipFile(zipFile zf, const char* srcFile, const char* dstLevel)
180 {
181     if(zf == NULL || srcFile == NULL) return __LINE__;
182 
183     int err=0;
184     int size_buf=0;
185     void* buf=NULL;
186     FILE * fin;
187     int size_read;
188     const char* filenameinzip = srcFile;
189     const char *savefilenameinzip;
190     zip_fileinfo zi;
191     int zip64 = 0;
192 
193     zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
194         zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
195     zi.dosDate = 0;
196     zi.internal_fa = 0;
197     zi.external_fa = 0;
198     filetime(filenameinzip,&zi.tmz_date,&zi.dosDate);
199 
200     zip64 = isLargeFile(filenameinzip);
201 
202     /* The path name saved, should not include a leading slash. */
203     /*if it did, windows/xp and dynazip couldn't read the zip file. */
204     savefilenameinzip = dstLevel;
205     while( savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/' )
206     {
207         savefilenameinzip++;
208     }
209 
210     err = zipOpenNewFileInZip3_64(zf, savefilenameinzip, &zi,
211         NULL, 0, NULL, 0, NULL /* comment*/,
212         Z_DEFLATED,
213         Z_DEFAULT_COMPRESSION,0,
214         -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
215         NULL, 0, zip64);
216 
217     if (err != ZIP_OK)
218         printf("error in opening %s in zipfile\n",filenameinzip);
219     else
220     {
221         fin = fopen64(filenameinzip,"rb");
222         if (fin==NULL)
223         {
224             err=ZIP_ERRNO;
225             printf("error in opening %s for reading\n",filenameinzip);
226         }
227     }
228 
229     if (err == ZIP_OK)
230     {
231         size_buf = WRITEBUFFERSIZE;
232         buf = (void*)malloc(size_buf);
233         if (buf==NULL)
234         {
235             printf("Error allocating memory\n");
236             err = ZIP_INTERNALERROR;
237         }
238         else
239         {
240             do
241             {
242                 err = ZIP_OK;
243                 size_read = (int)fread(buf,1,size_buf,fin);
244                 if (size_read < size_buf)
245                     if (feof(fin)==0)
246                     {
247                         printf("error in reading %s\n",filenameinzip);
248                         err = ZIP_ERRNO;
249                     }
250 
251                     if (size_read>0)
252                     {
253                         err = zipWriteInFileInZip (zf,buf,size_read);
254                         if (err<0)
255                         {
256                             printf("error in writing %s in the zipfile\n",
257                                 filenameinzip);
258                         }
259 
260                     }
261             } while ((err == ZIP_OK) && (size_read>0));
262 
263             free(buf);
264         }
265     }
266 
267     if (fin)
268         fclose(fin);
269 
270     if (err<0)
271         err=ZIP_ERRNO;
272     else
273     {
274         err = zipCloseFileInZip(zf);
275         if (err!=ZIP_OK)
276             printf("error in closing %s in the zipfile\n",
277             filenameinzip);
278     }
279 
280     return 0;
281 }
282 
283 int DoZipFile(const char* strFile, const char* dstLevel, const char* strZipFile, int replaceFlag)
284 {
285     int openMode = APPEND_STATUS_CREATE;
286     if (check_exist_file(strZipFile))
287     {
288         if (replaceFlag == RG_ZIP_FILE_APPEND)
289         {
290             openMode = APPEND_STATUS_ADDINZIP;
291         }
292         else
293         {
294             openMode = APPEND_STATUS_CREATE;
295         }
296     }
297 
298     zipFile zf;
299     zf = zipOpen64(strZipFile, openMode);
300     if (zf)
301     {
302         CStdString strDstLevel;
303         if(dstLevel) strDstLevel = dstLevel;
304         strDstLevel.Trim();
305         if(strDstLevel.IsEmpty())
306         {
307             strDstLevel = strFile;
308             if(strDstLevel.Right(1) == "\\" || strDstLevel.Right(1) == "/")
309                 strDstLevel = strDstLevel.Left(strDstLevel.GetLength() - 1);
310             int nFind = strDstLevel.ReverseFind('\\');
311             if(nFind == -1) nFind = strDstLevel.ReverseFind('/');
312             if(nFind != -1) 
313                 strDstLevel = strDstLevel.Mid(nFind);
314         }
315 
316         if (strDstLevel.Left(1) == "\\" || strDstLevel.Left(1) == "/") 
317             strDstLevel = strDstLevel.Right(strDstLevel.GetLength() - 1);
318 
319         DoZipFile(zf, strFile, strDstLevel.c_str());
320         zipClose(zf, NULL);
321         return 0;
322     }
323 
324     return 0;
325 }
326 
327 static int GetFilesFromDir(const char* strDir, vector<CStdString> &_fileInfo)
328 {
329 
330 #ifdef _WIN32
331     CStdString strFind = strDir;
332     CStdString strPath;
333     if (strFind.Right(1) != "\\")
334     {
335         strFind += "\\";
336     }
337     strPath = strFind;
338     strFind += "*.*";
339     
340     WIN32_FIND_DATA wfd;
341     HANDLE hFind = FindFirstFile(strFind, &wfd);
342     if (hFind != INVALID_HANDLE_VALUE)
343     {
344         while(FindNextFile(hFind, &wfd))
345         {
346             if (strcmp(wfd.cFileName, ".") == 0 || strcmp(wfd.cFileName, "..") == 0)
347             {
348                 continue;
349             }
350             CStdString strFilePath = strPath + wfd.cFileName;
351             if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
352             {
353                 GetFilesFromDir(strFilePath.c_str(), _fileInfo);
354             }
355             else
356             {
357                 _fileInfo.push_back(strFilePath);
358             }
359         }
360         FindClose(hFind);
361         return 0;
362     }
363     
364     return __LINE__;
365 #else
366     struct stat     statbuf;
367     struct dirent    *dirp;
368     DIR                *dp;
369     const char* szPath = strDir;
370 
371     if(lstat(szPath, &statbuf) < 0)
372     {
373         perror("lstat");
374         return __LINE__;
375     }
376     if(S_ISDIR(statbuf.st_mode) == 0)
377     {
378         _fileInfo.push_back(szPath);
379         return 0;
380     }
381 
382     if((dp = opendir(szPath)) == NULL)
383     {
384         perror("opendir");
385         return __LINE__;
386     }
387 
388     while((dirp = readdir(dp)) != NULL)
389     {
390         if(strcmp(dirp->d_name, ".") == 0 ||
391             strcmp(dirp->d_name, "..") == 0)
392             continue;
393 
394         std::string subDir = string(szPath) + "/";
395         subDir += dirp->d_name;
396         if(dirp->d_type == DT_REG)
397         {
398             _fileInfo.push_back(subDir);
399         }
400         else if(dirp->d_type == DT_DIR)    
401         {
402             GetFilesFromDir(subDir.c_str(), _fileInfo);
403         }
404     }
405 
406     closedir(dp);
407 #endif
408 }
409 
410 int DoZipDir(const char* strDir, const char* dstLevel, const char* strZipFile, int replaceFlag)
411 {
412     int openMode = APPEND_STATUS_CREATE;
413     if(check_exist_file(strZipFile))
414     {
415         if (replaceFlag == RG_ZIP_FILE_APPEND)
416         {
417             openMode = APPEND_STATUS_ADDINZIP;
418         }
419         else
420         {
421             remove(strZipFile);
422             openMode = APPEND_STATUS_CREATE;
423         }
424     }
425 
426     CStdString strDstLevel;
427     if(dstLevel) strDstLevel= dstLevel;
428     strDstLevel.Trim();
429     if(strDstLevel.IsEmpty()) {    //use current dir path as zip file path level 
430         strDstLevel = strDir;
431         if(strDstLevel.Right(1) == "/" || strDstLevel.Right(1) == "\\")    //remove the last slash
432             strDstLevel = strDstLevel.Left(strDstLevel.GetLength() - 1);
433 
434         int nFind = strDstLevel.ReverseFind('\\');    //now get the dst level in zip file
435         if(nFind == -1) nFind = strDstLevel.ReverseFind('/');
436         if(nFind != -1) strDstLevel = strDstLevel.Mid(nFind); 
437     }
438 
439     //add pending slash
440 #ifdef _WIN32
441     if(strDstLevel.Right(1) != "\\") strDstLevel += "\\";    
442 #else
443     if(strDstLevel.Right(1) != "/") strDstLevel += "/";
444 #endif
445 
446     //remove slash at the beginning of the string
447     if (strDstLevel.Left(1) == "\\" || strDstLevel.Left(1) == "/") 
448         strDstLevel = strDstLevel.Right(strDstLevel.GetLength() - 1);
449 
450     zipFile zf;
451     zf = zipOpen64(strZipFile, openMode);
452     if (zf)
453     {
454         vector<CStdString> _fileInfo;
455         GetFilesFromDir(strDir, _fileInfo);
456         for (size_t i = 0; i < _fileInfo.size(); ++i)
457         {
458             CStdString strFilePath = _fileInfo[i];
459             CStdString strFileLevel;
460             int nFind = strFilePath.Find(strDir);
461             if(nFind != -1) strFileLevel = strFilePath.Mid(strlen(strDir));
462 
463             if (strFileLevel.Left(1) == "\\" || strFileLevel.Left(1) == "/") 
464                 strFileLevel = strFileLevel.Right(strFileLevel.GetLength() - 1);
465                 
466             strFileLevel = strDstLevel + strFileLevel;
467             strFileLevel.Replace("\\", "/");
468 
469             DoZipFile(zf, strFilePath.c_str(), strFileLevel.c_str());
470 //            printf("%s\n%s\n", strFilePath.c_str(), strFileLevel.c_str());
471         }
472         
473         zipClose(zf, NULL);
474         return 0;
475     }
476     
477     return __LINE__;
478 }
479 
480 #ifdef _TESTZIP
481 int main(int argc, char* argv[])
482 {
483     if(argc < 2)
484     {
485         printf("Usage: %s zipfile filetozip\n", argv[0]);
486         getchar();
487         return 1;
488     }
489     const char* szZipFile = argv[1];
490     bool bFirst = true;
491     for(int i = 2; i < argc; ++i)
492     {
493         const char* filetozip = argv[i];
494         DWORD dwAttr = GetFileAttributes(filetozip);
495         if(dwAttr == INVALID_FILE_ATTRIBUTES)
496         {
497             printf("invalid file name: %s\n", filetozip);
498             continue;
499         }
500         if(dwAttr & FILE_ATTRIBUTE_DIRECTORY)
501         {
502             DoZipDir(filetozip, "", szZipFile, 
503                     bFirst ? RG_ZIP_FILE_REPLACE : RG_ZIP_FILE_APPEND);
504             bFirst = false;
505         }
506         else if(dwAttr & FILE_ATTRIBUTE_NORMAL)
507         {
508             DoZipFile(filetozip, "", szZipFile, 
509                     bFirst ? RG_ZIP_FILE_REPLACE : RG_ZIP_FILE_APPEND);
510             bFirst = false;
511         }
512     }
513 
514     getchar();
515 
516     return 0;
517 }
518 
519 #endif
View Code

相关文章: