- Zlib 1.2.11
- Minizip Zlib自带
关于 Zlib 的编译
这里只说 Zlib 在 Windows 上的编译. Linux/Mac 上的不再本次考虑范围内.
打开 cmd ,进入 zlib 所在的目录下
-
准备生成汇编(这里的汇编有问题, 后面编译的时候需要去掉这部分汇编)
-
x86
进入到
contrib\masmx86
目录下, 执行bld_m32.bat
文件, 生成需要的汇编代码 -
x64
进入到
contrib\masmx64
目录下, 执行bld_m64.bat
文件, 生成需要的汇编代码
-
进入
contrib\vstudio\vc14
(这里有很多 vc 版本, 选择自己电脑安装的即可) 目录下, 打开zlibvc.sln
工程.这时候会看到有六个工程项目. 其中, zlibvc 生成的是
动态库
, zlibstat 生成的是静态库
. 其它的基本上可以认定为是测试工程, 不需要处理修改
unzip.c
文件, 将#define NOUNCRYPT
这行代码注释掉. 默认情况下, zlib 是不支持密码加密的. 但是 minizip 支持.-
直接 build 即可.
笔者自带的三个配置: debug, release, releasewithoutasm.
- debug build 的时候, 提示了
error LINK2026: 模块对于 SAFESEH 映像是不安全
的问题. 这时候, 打开工程属性->连接器->命令行, 输入/SAFESEH:NO
到 附加选项 中即可. - relesae build 的时候, 无错误. 但是经过测试, 由于 release 分支使用了上面编译好的汇编代码. 上面也说过, 如果包含了这部分汇编的话, 解压缩的时候可能会再汇编代码这里引起内存崩溃的问题. 因此, 笔者没有用这个选项.
- releasewithoutasm. 这个选项没有包含汇编, 测试过程中没有发生内存崩溃的问题.
- debug build 的时候, 提示了
新建工程, 将上面编译好的库导入到工程中. 打开
contrib\minizip
目录下, 拷贝下面的除了minizip.c
与miniunz.c
的所有 h/c 文件 到新建的工程中.-
编写 unzip 代码. 如下:
ZipOperation.h
class ZipOperation { public: static bool Unzip(); private: static void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date); static int makedir(char *newdir); static int do_extract_currentfile(unzFile uf, const char* password); static int do_extract(unzFile uf, const char* password); };
ZipOperation.cpp
#include "ZipOperation.h" #include <fstream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <errno.h> #include <fcntl.h> #include <direct.h> #include <io.h> #include <Windows.h> #define CASESENSITIVITY (0) #define WRITEBUFFERSIZE (8192) #define MAXFILENAME (256) #ifdef _WIN32 #define USEWIN32IOAPI #include "iowin32.h" #endif void ZipOperation::change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date) { HANDLE hFile; FILETIME ftm, ftLocal, ftCreate, ftLastAcc, ftLastWrite; hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); GetFileTime(hFile, &ftCreate, &ftLastAcc, &ftLastWrite); DosDateTimeToFileTime((WORD)(dosdate >> 16), (WORD)dosdate, &ftLocal); LocalFileTimeToFileTime(&ftLocal, &ftm); SetFileTime(hFile, &ftm, &ftLastAcc, &ftm); CloseHandle(hFile); } int ZipOperation::makedir(char *newdir) { char *buffer = nullptr; char *p = nullptr; int len = (int)strlen(newdir); if (len <= 0) return 0; buffer = (char*)malloc(len + 1); if (buffer == nullptr) { printf("Error allocating memory\n"); return UNZ_INTERNALERROR; } strcpy(buffer, newdir); if (buffer[len - 1] == '/') { buffer[len - 1] = '\0'; } if (_mkdir(buffer) == 0) { free(buffer); return 1; } p = buffer + 1; while (true) { char hold; while (*p && *p != '\\' && *p != '/') p++; hold = *p; *p = 0; if ((_mkdir(buffer) == -1) && (errno == ENOENT)) { printf("couldn't create directory %s\n", buffer); free(buffer); return 0; } if (hold == 0) break; *p++ = hold; } free(buffer); return 1; } int ZipOperation::do_extract_currentfile(unzFile uf, const char* password) { char filename_inzip[256] = {0}; char* filename_withoutpath = nullptr; char* p = nullptr; int err = UNZ_OK; FILE *fout = nullptr; void* buf; uInt size_buf; unz_file_info64 file_info; uLong ratio = 0; err = unzGetCurrentFileInfo64(uf, &file_info, filename_inzip, sizeof(filename_inzip), nullptr, 0, nullptr, 0); if (err != UNZ_OK) { printf("error %d with zipfile in unzGetCurrentFileInfo\n", err); return err; } size_buf = WRITEBUFFERSIZE; buf = (void*)malloc(size_buf); if (buf == nullptr) { printf("Error allocating memory\n"); return UNZ_INTERNALERROR; } p = filename_withoutpath = filename_inzip; while ((*p) != '\0') { if (((*p) == '/') || ((*p) == '\\')) filename_withoutpath = p + 1; p++; } if ((*filename_withoutpath) == '\0') { printf("creating directory: %s\n", filename_inzip); _mkdir(filename_inzip); } else { const char* write_filename = filename_inzip; int skip = 0; err = unzOpenCurrentFilePassword(uf, password); if (err != UNZ_OK) { printf("error %d with zipfile in unzOpenCurrentFilePassword\n", err); } if ((skip == 0) && (err == UNZ_OK)) { fout = fopen64(write_filename, "wb"); /* some zipfile don't contain directory alone before file */ if ((fout == nullptr) && (filename_withoutpath != (char*)filename_inzip)) { char c = *(filename_withoutpath - 1); *(filename_withoutpath - 1) = '\0'; makedir(const_cast<char*>(write_filename)); *(filename_withoutpath - 1) = c; fout = fopen64(write_filename, "wb"); } if (fout == nullptr) { printf("error opening %s\n", write_filename); } } if (fout != nullptr) { printf(" extracting: %s\n", write_filename); do { err = unzReadCurrentFile(uf, buf, size_buf); if (err < 0) { printf("error %d with zipfile in unzReadCurrentFile\n", err); break; } if (err > 0) if (fwrite(buf, err, 1, fout) != 1) { printf("error in writing extracted file\n"); err = UNZ_ERRNO; break; } } while (err > 0); if (fout) fclose(fout); if (err == 0) change_file_date(write_filename, file_info.dosDate, file_info.tmu_date); } if (err == UNZ_OK) { err = unzCloseCurrentFile(uf); if (err != UNZ_OK) { printf("error %d with zipfile in unzCloseCurrentFile\n", err); } } else { unzCloseCurrentFile(uf); /* don't lose the error */ } } free(buf); return err; } int ZipOperation::do_extract(unzFile uf, const char* password) { unz_global_info64 gi; int err; err = unzGetGlobalInfo64(uf, &gi); if (err != UNZ_OK) { printf("error %d with zipfile in unzGetGlobalInfo \n", err); } for (uLong i = 0; i < gi.number_entry; i++) { if (do_extract_currentfile(uf, password) != UNZ_OK) { break; } if ((i + 1) < gi.number_entry) { err = unzGoToNextFile(uf); if (err != UNZ_OK) { printf("error %d with zipfile in unzGoToNextFile\n", err); break; } } } return 0; } bool ZipOperation::Unzip() { const char *zipfilename = "C:\\Users\\lma\\Desktop\\file\\paper.zip";//—πÀıŒƒº˛√˚ const char *password = "ktceFuoz5bQxqn1Dl1IuAeFTFTZdZblgSbY5Idtqiy8=";//√‹¬Î char filename_try[MAXFILENAME + 16] = ""; int ret_value = 0; const char *dirname = "C:\\Users\\lma\\Desktop\\file\\paper\\"; unzFile uf = nullptr; zlib_filefunc64_def ffunc; strncpy(filename_try, zipfilename, MAXFILENAME - 1); filename_try[MAXFILENAME] = '\0'; fill_win32_filefunc64A(&ffunc); uf = unzOpen2_64(zipfilename, &ffunc); if (uf == nullptr) { strcat(filename_try, ".zip"); uf = unzOpen2_64(filename_try, &ffunc); } if (uf == nullptr) { printf("Cannot open %s or %s.zip\n", zipfilename, zipfilename); return false; } printf("%s opened\n", filename_try); makedir(const_cast<char*>(dirname)); if (_chdir(dirname)) { printf("Error changing into %s, aborting\n", dirname); return false; } ret_value = do_extract(uf, password); unzClose(uf); return true; }