[Windows/C] libzip 的编译和使用

[复制链接]
发表于 2026-3-8 01:23:49 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本文参考:

  • Windwos zlib 下载和编译
  • Windwos 编译 libzip
0. 预备工作

编译器:我使用的编译器是 gcc(MinGW),此时需将编译器目次下的 mingw32-make.exe 改名为 make.exe,方便使用。
你必要 CMake,可以在 https://cmake.org/download/ 下载。下载解压后在 bin 目次下找到 cmake-gui.exe,我们使用的是这个 GUI 步伐。cmake.exe 是它的下令行版本,不发起直接使用。
1. 编译 zlib

libzip 依赖 zlib,以是你必要先编译 zlib。
先在 https://www.zlib.net/ 下载 zlib 源码,下载链接大概在
The current release is publicly available here:
这一行下面。可以看到在其根目次下有 CMakeLists.txt 文件。
打开 cmake-gui.exe,在第一行 Where is the source code: 右边选择你的 zlib 源码目次(有 CMakeLists.txt 文件的),在第三行 Where to build the binaries: 右边选择编译结果目次,恣意放哪都行。
点击左下角 Configure 选择构建工具。MinGW 就选择 MinGW Makefiles。
留意下面有四个选项,它默认选第一项 Use default native compilers,但没用,请选择第二项 Specify native compilers,然后点击 Next 选择编译器路径。编译 C 语言的步伐名是 gcc.exe,C++ 的是 g++.exe,Fortran 的是 gfortran.exe,自行找到相应步伐即可。然后点击 Finish。
假如选错了,点击 Configure 不能重新设置。可以在左上角的 File -> Delete Cache 清空缓存再重新设置。
此时下面的日志日志一样寻常会报错,关键词 CMake was unable to find a build program corresponding to "MinGW Makefiles". CMAKE_MAKE_PROGRAM is not set. 那就在上方的选项中搜刮 CMAKE_MAKE_PROGRAM 并设置 make.exe 的路径即可。留意你大概必要在右上方勾选 Grouped 和 Advanced 以分组和表现更多选项。
点击 Configure,实行设置查抄。查抄完毕后上方会出现新的设置选项,包罗 CPACK 和 ZLIB 等,按需选择。我必要 zip 功能,以是勾选 zip 相干的选项。
点击 Generate,开始天生。天生完毕后打开你选择的编译结果目次,在此处打开下令行实行 make 举行编译。编译完成即可得到 libz.dll。
2. 编译 libzip

在 https://libzip.org/download/ 下载 libzip 源码。在其根目次下同样有 CMakeLists.txt 文件。
打开 cmake-gui.exe,同上选择相干目次。
点击 Configure 会报错,关键词 Could NOT find ZLIB (missing: ZLIB_LIBRARY ZLIB_INCLUDE_DIR)。由于 libzip 依赖 zlib,以是必须在上方的选项中设置 ZLIB 相干的选项,包罗 ZLIB_INCLUDE_DIR:zlib 源码目次,ZLIB_LIBRARY_DEBUG 和 ZLIB_LIBRARY_RELEASE:编译 zlib 得到的 libz.dll。
点击 Generate,开始天生。会出现 Warning,可以不消管,假如不想看到就在上方搜刮相干选项关闭即可。天生完毕后同上实行 make 举行编译。编译完成即可得到 libzip.dll。
3. 使用 libzip

这里给出一个测试用例 demo.c,功能是打开当前目次下的 test.zip 并解压此中的 a.txt:
留意必要把 zip.h(在 libzip 源码的 lib 目次中)复制到步伐地点目次,以及 zip.h 引用的 zipconf.h。
  1. #include <errno.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "zip.h"
  6. int main(void) {
  7.   const char* zip_path = "test.zip";
  8.   const char* target_name = "a.txt";
  9.   const char* output_name = "a.txt";
  10.   zip_t* archive = NULL;  // 打开的 ZIP 归档
  11.   zip_file_t* zf = NULL;  // 打开的 ZIP 内文件
  12.   zip_stat_t sb;          // 文件统计信息
  13.   zip_error_t error;      // 错误对象
  14.   FILE* out_fp = NULL;    // 输出文件指针
  15.   char buf[8192];         // 读缓冲区
  16.   zip_int64_t bytes_read;
  17.   size_t bytes_written;
  18.   zip_int64_t index;
  19.   int err = 0;
  20.   /* 1. 打开 ZIP 归档(只读模式) */
  21.   archive = zip_open(zip_path, ZIP_RDONLY, &err);
  22.   if (archive == NULL) {
  23.     zip_error_init_with_code(&error, err);
  24.     fprintf(stderr, "无法打开 ZIP 文件 '%s':%s\n", zip_path,
  25.             zip_error_strerror(&error));
  26.     zip_error_fini(&error);
  27.     return 1;
  28.   }
  29.   /* 2. 根据文件名查找在归档中的索引 */
  30.   index = zip_name_locate(archive, target_name, 0);
  31.   if (index < 0) {
  32.     fprintf(stderr, "ZIP 中未找到文件 '%s'\n", target_name);
  33.     zip_close(archive);
  34.     return 1;
  35.   }
  36.   /* 3. 获取文件信息(大小、CRC 等)——可选,但可用于进度显示 */
  37.   if (zip_stat_index(archive, index, 0, &sb) == 0) {
  38.     printf("正在解压 '%s',大小:%llu 字节\n", target_name,
  39.            (unsigned long long)sb.size);
  40.   }
  41.   /* 4. 打开 ZIP 内的目标文件 */
  42.   zf = zip_fopen_index(archive, index, 0);
  43.   if (zf == NULL) {
  44.     fprintf(stderr, "无法打开 ZIP 内的文件 '%s':%s\n", target_name,
  45.             zip_strerror(archive));
  46.     zip_close(archive);
  47.     return 1;
  48.   }
  49.   /* 5. 创建输出文件(二进制写模式) */
  50.   out_fp = fopen(output_name, "wb");
  51.   if (out_fp == NULL) {
  52.     fprintf(stderr, "无法创建输出文件 '%s':%s\n", output_name,
  53.             strerror(errno));
  54.     zip_fclose(zf);
  55.     zip_close(archive);
  56.     return 1;
  57.   }
  58.   /* 6. 循环读取 ZIP 内文件内容并写入磁盘 */
  59.   while ((bytes_read = zip_fread(zf, buf, sizeof(buf))) > 0) {
  60.     bytes_written = fwrite(buf, 1, (size_t)bytes_read, out_fp);
  61.     if (bytes_written != (size_t)bytes_read) {
  62.       fprintf(stderr, "写入文件失败(磁盘空间不足?)\n");
  63.       fclose(out_fp);
  64.       zip_fclose(zf);
  65.       zip_close(archive);
  66.       return 1;
  67.     }
  68.   }
  69.   /* 检查读取过程中是否发生错误 */
  70.   if (bytes_read < 0) {
  71.     fprintf(stderr, "读取 ZIP 内容时出错:%s\n", zip_file_strerror(zf));
  72.     fclose(out_fp);
  73.     zip_fclose(zf);
  74.     zip_close(archive);
  75.     return 1;
  76.   }
  77.   /* 7. 关闭所有句柄,释放资源 */
  78.   fclose(out_fp);
  79.   zip_fclose(zf);
  80.   zip_close(archive);
  81.   printf("成功解压 '%s' 到当前目录。\n", target_name);
  82.   return 0;
  83. }
复制代码
将 libz.dll 和 libzip.dll 复制到步伐地点目次并编译:
  1. gcc demo.c libzip.dll -o demo.exe -Wall -Wextra
复制代码
编译完成后运行 demo.exe 检察结果。留意步伐地点目次中必须要有 libz.dll 和 libzip.dll 才气运行。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表