首先了解zlib 历史
- zlib的概述。https://zlib.net/
- zlib的版本。https://zlib.net/
- zlib的cmake 编译出不同平台库,首先的准备好源码(源码可在https://zlib.net/ 中下载)。编译界面了下网络大神的 理解很透彻。
进入到zlib-1.2.11目录下,发现有个Makefile文件,打开如下,
这是个提示,让我们先运行./configure。按照提示我们在终端输入./configure并回车,运行完毕后再打开看Makefile,发现里面就有内容了,
此时在终端输入make,这样zlib源码就开始编译了。
编译完毕后如果输入make install,就可以把编译好的zlib库放在系统路径里,以后写代码就可以直接调用zlib提供的库函数了。
以上这些操作信息是写在源码目录下的readme文件里的,这里截取一段,
还有讲example的,告诉我们example源码在哪,
源码目录下还有个INDEX文件,里面叙述了构成zlib的所有public header files和private source files,有了这些信息,就可以很方便的把需要的源码集成到自己的工程中去。
可以看出作者的文档写的非常好。
使用minizip 比较简单
minizip解压多文件!minizip源码目录在zlib-1.2.11/contrib目录下。
将一下文件 引入到项目中使用即可:
具体使用的例子:
//解压代码片段 本例子将代码解压到和zip文件同一目录下
void ZipUtil::UnzipFile(const char *strFilePath)
{
// LOGDBG("===========================");
clock_t start = clock();
if (strFilePath == NULL || strlen(strFilePath) == 0) {
printf("Zip Path Error!%s\n", strFilePath);
return;
}
std::string rootPath = strFilePath;
if (rootPath.substr(rootPath.find_last_of(".")).compare(ZIP_SUFFIX) != 0) {
printf("File Type Error!%s \t", strFilePath);
return;
}
rootPath = rootPath.substr(0, rootPath.find_last_of("/")) + "/";
unzFile zipFile = unzOpen(strFilePath);// Open the zip file
if (zipFile == NULL) {
printf("not found\n");
return;
}
unz_global_info globalInfo;
if (UNZ_OK != unzGetGlobalInfo(zipFile, &globalInfo)) {
printf("获取全局zip信息失败!\n");
unzClose(zipFile);
zipFile = NULL;
return;
}
int zipInfo = unzGoToFirstFile(zipFile);
if (UNZ_OK != zipInfo) {
printf("无法获取zip包内文件信息zip包可能是null的!\n");
unzClose(zipFile);
zipFile = NULL;
return;
}
char read_buffer[READ_SIZE];
uLong i;
for (i = 0; i < globalInfo.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;
}
//名字拼接 解压到同一目录下
std::string fileNameStr = rootPath + filename;
strncpy(filename, fileNameStr.c_str(), fileNameStr.length() + 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, 0775);
}
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;
}
// 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;
}
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;
}
// 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) < globalInfo.number_entry) {
if (unzGoToNextFile(zipFile) != UNZ_OK) {
printf("cound not read next file\n");
unzClose(zipFile);
return;
}
}
}
unzClose(zipFile);
clock_t end = clock();
printf("Elapsed Time %f\n", (double) (end - start));
}
备注
在应用到Android的时候报错:
类似下面代码,主要是因为Android这边没有进行宏定义
/jni/ioapi.c:127: error: undefined reference to 'fopen64'
/jni/ioapi.c:157: error: undefined reference to 'ftello64'
/jni/ioapi.c:203: error: undefined reference to 'fseeko64'
/jni/miniunz.c:380: error: undefined reference to 'fopen64'
/jni/miniunz.c:411: error: undefined reference to 'fopen64'
/jni/miniunz.c:420: error: undefined reference to 'fopen64'
解决办法:修改contrib/minizip/ioapi.h, 增加以下宏定义即可:
#ifdef __ANDROID__
#define fopen64 fopen
#ifdef __USE_FILE_OFFSET64
#define ftello64 ftello
#define fseeko64 fseeko
#else
#define ftello64 ftell
#define fseeko64 fseek
#endif
#endif