将 zlib 引入到C++项目中 历程

首先了解zlib 历史

  1. zlib的概述。https://zlib.net/
  2. zlib的版本。https://zlib.net/
  3. 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

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值