[Windows/C] libzip 的编译和使用
这一行下面。可以看到在其根目录下有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.exeC 的是g.exeFortran 的是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_DIRzlib 源码目录ZLIB_LIBRARY_DEBUG和ZLIB_LIBRARY_RELEASE编译 zlib 得到的libz.dll。点击Generate开始生成。会出现 Warning可以不用管如果不想看到就在上方搜索相关选项关闭即可。生成完毕后同上执行make进行编译。编译完成即可在结果目录的lib目录下得到libzip.dll。3. 使用 libzip#这里给出一个测试用例demo.c功能是打开当前目录下的test.zip并解压其中的a.txt注意需要把zip.h在 libzip 源码的lib目录中复制到程序所在目录以及zip.h引用的zipconf.h。#include errno.h #include stdio.h #include stdlib.h #include string.h #include zip.h int main(void) { const char* zip_path test.zip; const char* target_name a.txt; const char* output_name a.txt; zip_t* archive NULL; // 打开的 ZIP 归档 zip_file_t* zf NULL; // 打开的 ZIP 内文件 zip_stat_t sb; // 文件统计信息 zip_error_t error; // 错误对象 FILE* out_fp NULL; // 输出文件指针 char buf[8192]; // 读缓冲区 zip_int64_t bytes_read; size_t bytes_written; zip_int64_t index; int err 0; /* 1. 打开 ZIP 归档只读模式 */ archive zip_open(zip_path, ZIP_RDONLY, err); if (archive NULL) { zip_error_init_with_code(error, err); fprintf(stderr, 无法打开 ZIP 文件 %s%s\n, zip_path, zip_error_strerror(error)); zip_error_fini(error); return 1; } /* 2. 根据文件名查找在归档中的索引 */ index zip_name_locate(archive, target_name, 0); if (index 0) { fprintf(stderr, ZIP 中未找到文件 %s\n, target_name); zip_close(archive); return 1; } /* 3. 获取文件信息大小、CRC 等——可选但可用于进度显示 */ if (zip_stat_index(archive, index, 0, sb) 0) { printf(正在解压 %s大小%llu 字节\n, target_name, (unsigned long long)sb.size); } /* 4. 打开 ZIP 内的目标文件 */ zf zip_fopen_index(archive, index, 0); if (zf NULL) { fprintf(stderr, 无法打开 ZIP 内的文件 %s%s\n, target_name, zip_strerror(archive)); zip_close(archive); return 1; } /* 5. 创建输出文件二进制写模式 */ out_fp fopen(output_name, wb); if (out_fp NULL) { fprintf(stderr, 无法创建输出文件 %s%s\n, output_name, strerror(errno)); zip_fclose(zf); zip_close(archive); return 1; } /* 6. 循环读取 ZIP 内文件内容并写入磁盘 */ while ((bytes_read zip_fread(zf, buf, sizeof(buf))) 0) { bytes_written fwrite(buf, 1, (size_t)bytes_read, out_fp); if (bytes_written ! (size_t)bytes_read) { fprintf(stderr, 写入文件失败磁盘空间不足\n); fclose(out_fp); zip_fclose(zf); zip_close(archive); return 1; } } /* 检查读取过程中是否发生错误 */ if (bytes_read 0) { fprintf(stderr, 读取 ZIP 内容时出错%s\n, zip_file_strerror(zf)); fclose(out_fp); zip_fclose(zf); zip_close(archive); return 1; } /* 7. 关闭所有句柄释放资源 */ fclose(out_fp); zip_fclose(zf); zip_close(archive); printf(成功解压 %s 到当前目录。\n, target_name); return 0; }