跨平台的zip文件压缩处理,支持压缩解压文件夹

根据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

 

解压缩API实现,其中的CStdString可以使用CString代替,接口与CString一致。

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

  1 /*
  2 miniunz.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 #ifndef _WIN32
 16 #ifndef __USE_FILE_OFFSET64
 17 #define __USE_FILE_OFFSET64
 18 #endif
 19 #ifndef __USE_LARGEFILE64
 20 #define __USE_LARGEFILE64
 21 #endif
 22 #ifndef _LARGEFILE64_SOURCE
 23 #define _LARGEFILE64_SOURCE
 24 #endif
 25 #ifndef _FILE_OFFSET_BIT
 26 #define _FILE_OFFSET_BIT 64
 27 #endif
 28 #endif
 29 
 30 #include <stdio.h>
 31 #include <stdlib.h>
 32 #include <string.h>
 33 #include <time.h>
 34 #include <errno.h>
 35 #include <fcntl.h>
 36 
 37 #ifdef _LINUX
 38 #include <unistd.h>
 39 #include <utime.h>
 40 #include <sys/stat.h>
 41 #include <sys/types.h>
 42 #else
 43 #include <direct.h>
 44 #include <io.h>
 45 #include <Windows.h>
 46 #endif
 47 
 48 #include "unzip.h"
 49 #include "stdstring.h"
 50 
 51 #define CASESENSITIVITY (0)
 52 #define WRITEBUFFERSIZE (8192)
 53 #define MAXFILENAME (256)
 54 
 55 /*
 56 #ifdef _WIN32
 57 #define USEWIN32IOAPI
 58 #include "iowin32.h"
 59 #endif
 60 */
 61 /*
 62 mini unzip, demo of unzip package
 63 
 64 usage :
 65 Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir]
 66 
 67 list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT
 68 if it exists
 69 */
 70 
 71 
 72 /* change_file_date : change the date/time of a file
 73 filename : the filename of the file where date/time must be modified
 74 dosdate : the new date at the MSDos format (4 bytes)
 75 tmu_date : the SAME new date at the tm_unz format */
 76 static void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date)
 77 {
 78 #ifdef _WIN32
 79     HANDLE hFile;
 80     FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
 81 
 82     hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE,
 83         0,NULL,OPEN_EXISTING,0,NULL);
 84     GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
 85     DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);
 86     LocalFileTimeToFileTime(&ftLocal,&ftm);
 87     SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
 88     CloseHandle(hFile);
 89 #else
 90 #ifdef _LINUX
 91     struct utimbuf ut;
 92     struct tm newdate;
 93     newdate.tm_sec = tmu_date.tm_sec;
 94     newdate.tm_min=tmu_date.tm_min;
 95     newdate.tm_hour=tmu_date.tm_hour;
 96     newdate.tm_mday=tmu_date.tm_mday;
 97     newdate.tm_mon=tmu_date.tm_mon;
 98     if (tmu_date.tm_year > 1900)
 99         newdate.tm_year=tmu_date.tm_year - 1900;
100     else
101         newdate.tm_year=tmu_date.tm_year ;
102     newdate.tm_isdst=-1;
103 
104     ut.actime=ut.modtime=mktime(&newdate);
105     utime(filename,&ut);
106 #endif
107 #endif
108 }
109 
110 
111 /* mymkdir and change_file_date are not 100 % portable
112 As I don't know well Unix, I wait feedback for the unix portion */
113 
114 static int mymkdir(const char* dirname)
115 {
116     int ret=0;
117 #ifdef _WIN32
118     ret = _mkdir(dirname);
119 #else
120 #ifdef _LINUX
121     ret = mkdir (dirname,0775);
122 #endif
123 #endif
124     return ret;
125 }
126 
127 int makedir (const char *newdir)
128 {
129     char *buffer ;
130     char *p;
131     int  len = (int)strlen(newdir);
132 
133     if (len <= 0)
134         return 0;
135 
136     buffer = (char*)malloc(len+1);
137     if (buffer==NULL)
138     {
139         printf("Error allocating memory\n");
140         return UNZ_INTERNALERROR;
141     }
142     strcpy(buffer,newdir);
143 
144     if (buffer[len-1] == '/') {
145         buffer[len-1] = '\0';
146     }
147     if (mymkdir(buffer) == 0)
148     {
149         free(buffer);
150         return 1;
151     }
152 
153     p = buffer+1;
154     while (1)
155     {
156         char hold;
157 
158         while(*p && *p != '\\' && *p != '/')
159             p++;
160         hold = *p;
161         *p = 0;
162         if ((mymkdir(buffer) == -1) && (errno == ENOENT))
163         {
164             printf("couldn't create directory %s\n",buffer);
165             free(buffer);
166             return 0;
167         }
168         if (hold == 0)
169             break;
170         *p++ = hold;
171     }
172     free(buffer);
173     return 1;
174 }
175 
176 static int do_extract_currentfile(unzFile uf, const char* password)
177 {
178     char filename_inzip[256];
179     char* filename_withoutpath;
180     char* p;
181     int err=UNZ_OK;
182     FILE *fout=NULL;
183     void* buf;
184     uInt size_buf;
185 
186     unz_file_info64 file_info;
187     uLong ratio=0;
188     err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
189 
190     if (err!=UNZ_OK)
191     {
192         printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
193         return err;
194     }
195 
196     size_buf = WRITEBUFFERSIZE;
197     buf = (void*)malloc(size_buf);
198     if (buf==NULL)
199     {
200         printf("Error allocating memory\n");
201         return UNZ_INTERNALERROR;
202     }
203 
204     p = filename_withoutpath = filename_inzip;
205     while ((*p) != '\0')
206     {
207         if (((*p)=='/') || ((*p)=='\\'))
208             filename_withoutpath = p+1;
209         p++;
210     }
211 
212     if ((*filename_withoutpath)=='\0')
213     {
214         mymkdir(filename_inzip);
215     }
216     else
217     {
218         const char* write_filename;
219 
220         write_filename = filename_inzip;
221 
222         err = unzOpenCurrentFilePassword(uf,password);
223         if (err==UNZ_OK)
224         {
225             fout=fopen64(write_filename,"wb");
226 
227             /* some zipfile don't contain directory alone before file */
228             if ((fout==NULL) &&
229                 (filename_withoutpath!=(char*)filename_inzip))
230             {
231                 char c=*(filename_withoutpath-1);
232                 *(filename_withoutpath-1)='\0';
233                 makedir(write_filename);
234                 *(filename_withoutpath-1)=c;
235                 fout=fopen64(write_filename,"wb");
236             }
237 
238             if (fout==NULL)
239             {
240                 printf("error opening %s\n",write_filename);
241             }
242         }
243         else
244         {
245             printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
246         }
247 
248         if (fout!=NULL)
249         {
250             do
251             {
252                 err = unzReadCurrentFile(uf,buf,size_buf);
253                 if (err<0)
254                 {
255                     printf("error %d with zipfile in unzReadCurrentFile\n",err);
256                     break;
257                 }
258                 if (err>0)
259                     if (fwrite(buf,err,1,fout)!=1)
260                     {
261                         printf("error in writing extracted file\n");
262                         err=UNZ_ERRNO;
263                         break;
264                     }
265             }
266             while (err>0);
267             if (fout)
268                 fclose(fout);
269 
270             if (err==UNZ_OK)
271                 change_file_date(write_filename,file_info.dosDate,
272                 file_info.tmu_date);
273         }
274 
275         if (err==UNZ_OK)
276         {
277             err = unzCloseCurrentFile (uf);
278             if (err!=UNZ_OK)
279             {
280                 printf("error %d with zipfile in unzCloseCurrentFile\n",err);
281             }
282         }
283         else
284             unzCloseCurrentFile(uf); /* don't lose the error */
285     }
286 
287     free(buf);
288     return err;
289 }
290 
291 
292 static int do_extract(unzFile uf, const char* password)
293 {
294     uLong i;
295     unz_global_info64 gi;
296     int err;
297     FILE* fout=NULL;
298 
299     err = unzGetGlobalInfo64(uf,&gi);
300     if (err!=UNZ_OK)
301         printf("error %d with zipfile in unzGetGlobalInfo \n",err);
302 
303     for (i=0;i<gi.number_entry;i++)
304     {
305         if (do_extract_currentfile(uf, password) != UNZ_OK)
306             break;
307 
308         if ((i+1) < gi.number_entry)
309         {
310             err = unzGoToNextFile(uf);
311             if (err!=UNZ_OK)
312             {
313                 printf("error %d with zipfile in unzGoToNextFile\n",err);
314                 break;
315             }
316         }
317     }
318 
319     return 0;
320 }
321 
322 static int do_extract_onefile(unzFile uf, const char* filename, const char* password)
323 {
324     int err = UNZ_OK;
325     if (unzLocateFile(uf,filename,CASESENSITIVITY)!=UNZ_OK)
326     {
327         printf("file %s not found in the zipfile\n",filename);
328         return 2;
329     }
330 
331     if (do_extract_currentfile(uf, password) == UNZ_OK)
332         return 0;
333     else
334         return 1;
335 }
336 
337 
338 int DoUnzip(const char* szZipFile, const char* szTargetDir)
339 {
340     if (szZipFile == NULL)
341     {
342         return __LINE__;
343     }
344     
345     CStdString dirname;
346     if(szTargetDir) dirname = szTargetDir;
347     dirname.Trim();
348 
349     unzFile uf = unzOpen64(szZipFile);
350     if (uf)
351     {
352 #ifdef _WIN32
353         if (!dirname.IsEmpty() && _chdir(dirname.c_str()))
354 #else
355         if (!dirname.IsEmpty() && chdir(dirname.c_str()))
356 #endif
357         {
358             printf("Error changing into %s, aborting\n", dirname.c_str());
359             return __LINE__;
360         }
361 
362         do_extract(uf, NULL);
363 
364         unzClose(uf);
365         return 0;
366     }
367     
368     return __LINE__;
369 }
370 
371 int DoUnzipFile(const char* szZipFile, const char* srcFileToExtract, const char* szTargetDir)
372 {
373     if (szZipFile == NULL)
374     {
375         return __LINE__;
376     }
377 
378     CStdString dirname;
379     if(szTargetDir) dirname = szTargetDir;
380     dirname.Trim();
381 
382     unzFile uf = unzOpen64(szZipFile);
383     if (uf)
384     {
385 #ifdef _WIN32
386         if (!dirname.IsEmpty() && _chdir(dirname.c_str()))
387 #else
388         if (!dirname.IsEmpty() && chdir(dirname.c_str()))
389 #endif
390         {
391             printf("Error changing into %s, aborting\n", dirname.c_str());
392             return __LINE__;
393         }
394 
395         do_extract_onefile(uf, srcFileToExtract, NULL);
396 
397         unzClose(uf);
398         return 0;
399     }
400 
401     return __LINE__;
402 }
403 
404 #ifdef _TESTUNZIP
405 int main(int argc, char* argv[])
406 {
407     if(argc < 1)
408     {
409         printf("Usage: %s zipfile\n", argv[0]);
410         return 1;
411     }
412 
413     bool bExtractSingalFile = false;
414     for(int i = 1; i < argc; ++i)
415     {
416         if(strcmp(argv[i], "-s") == 0)
417         {
418             if(i + 1 < argc)
419             {
420                 i++;
421                 const char* filetoextract = argv[i];
422                 printf("extract singal file %s\n", filetoextract);
423                 i++;
424                 if(i < argc)
425                 {
426                     DoUnzipFile(argv[i++], filetoextract, NULL);
427                 }
428             }
429         }
430         else
431             DoUnzip(argv[i], NULL);
432     }
433 
434     return 0;
435 }
436 #endif
View Code

 

转载于:https://www.cnblogs.com/jojodru/p/4123797.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值