资讯动态

QuaZip预编译库接入指南:Qt版本、MSVC/MinGW选型与DLL部署避坑

发布时间:2026/10/16 6:45:57 来源:尧图企业网站定制
简介QuaZip是开源的C压缩处理库支持ZIP档案的读取、创建、更新并对RAR格式提供基础操作能力。这份已编译好的lib与dll资源包面向Windows环境下使用Qt5或Visual Studio的C开发者帮助其快速获得可用的压缩模块免去自行编译源码、配置Qt依赖的繁琐过程。压缩包共29个文件包含头文件h、CMake配置、静态库lib、动态库dll及pkg-config文件整体仅427KB按include、lib、bin目录组织结构与Qt5常见安装布局一致便于工程直接引用。已有599人学习下载链接lib后还需将对应dll置于运行目录或PATH中即可开始使用。静态库与动态库版本齐全可灵活选择链接方式借助QuaZip和QuaZipFile等接口能直接实现ZIP档案遍历、解压、添加与删除并借助错误处理机制排查传输或读写异常适合中高级C开发者用于压缩相关模块的开发。1. QuaZip 编译好的库 lib、dll先对齐版本再接线少走三小时弯路给 C/Qt 项目加 ZIP 压缩解压QuaZip 是比直接调 zlib 舒服得多的封装层。下载一份别人编译好的 QuaZip 库lib、dll 都摆在眼前理论上开箱即用。但我见过太多人卡在这一步拿到库直接往工程里塞链接报错一串查来查去发现是 Qt 版本、编译器、位数甚至 Debug/Release 有一个对不上整个下午就耗在“黑匣子”里翻车。QuaZip 编译产物跟 Qt 版本强绑定对不上就是编译通过、运行崩溃。这篇文章从编译原理讲起把预编译库的选型、接入、部署和排错流程完整拆一遍适合想绕开自编译的 Qt 开发者也适合被 CMake 折腾到头秃、只想拿 lib、dll 快速交付的老手。读完你就能准确判断资源包里哪一份库是你当前工程真正该用的。2. 自己走一遍 QuaZip 编译CMake 参数、zlib 依赖和 MSVC/MinGW 产物差异很多拿到预编译库的人第一反应是“能用就行”等到对不上号时才回头补课。与其到时候靠玄学猜不如先把 QuaZip 的编译链路看明白。搞清这一步后面接入和排错会顺很多。2.1 QuaZip 源码、zlib 和 Qt编译 QuaZip 的三件套QuaZip 本身是一组 C 类的集合核心类包括QuaZip、QuaZipFile、QuaZipFileInfo、QuaZipDir、QuaZipNewInfo。它不自己实现压缩算法底层压的是 zlib对上层的 IO 抽象则依赖 QtCore。也就是说编译 QuaZip 至少需要三样东西QuaZip 源码、zlib 的头文件与库、以及一套和你目标工程一致的 Qt 环境。提示QuaZip 是 zlib 的 Qt 封装编译时要同时满足 zlib 和 QtCore 两个依赖任何一个版本错位出来的 lib、dll 都是残品。我在实际项目里习惯把编译产物按“头文件、导入库、动态库”三部分理解头文件负责编译期类型检查导入库负责链接器找符号动态库负责程序运行时真正干活。预编译资源包里通常也是这种结构接入工程时三部分都要放对缺一个都会出问题。2.2 一条 CMake 命令编译 QuaZip参数和产物路径自己编译 QuaZip 其实不复杂前提是你已经装好了 Qt 和 CMake。源码包根目录一般自带CMakeLists.txt常见做法是开一个 build 目录把构建配置和源码目录分开cmake -B build -S . \ -DCMAKE_PREFIX_PATHC:/Qt/6.5.3/msvc2019_64 \ -DQUAZIP_BUILD_SHAREDON \ -DQUAZIP_BUILD_TESTSOFF cmake --build build --config Release --target quazip说明CMAKE_PREFIX_PATH用来告诉 CMake “Qt 装在哪个目录”CMake 会从里面找 Qt 的 CMake config 文件路径填错的话第一步就会报找不到 QtQUAZIP_BUILD_SHAREDON表示生成动态库也就是我们要的 quazip.dllQUAZIP_BUILD_TESTSOFF是关掉测试目标避免构建链上拖进 Qt Test 等额外依赖。构建完成后Release 配置下会生成动态库和导入库如果希望在工程里直接用这份产物后续配合第 3 章的目录规划放入工程即可。2.3 MSVC 与 MinGW两套 lib、dll 无法互用QuaZip 在不同工具链下生成的库文件名不一样这点是接入预编译库最容易踩的坑。MSVC 工具链产出的是quazip.lib加quazip.dllMinGW 工具链产出的是libquazip.dll.a加quazip.dll。也就是说动态库文件名可能相同但导入库完全不同链接器不认识对方的格式。工具链导入库动态库附带依赖MSVCVS2019/2022quazip.libquazip.dllmsvcp140.dll、vcruntime140.dllMinGWQt 自带工具链libquazip.dll.aquazip.dlllibgcc_s_seh-1.dll、libstdc-6.dll所以接入前一定要确认工程当前的套件是 MSVC 还是 MinGW。有人把 MSVC 编译的库硬塞到 MinGW 工程里CMake 配置阶段不报错链接阶段直接黑盒报错就是因为导入库格式不兼容。Qt 的安装目录命名通常会有提示比如msvc2019_64和mingw_64这个信息比配置文件里的任何文字都可靠。2.4 既然能编译为什么还推荐用预编译好的库自己编译 QuaZip 的优势是版本可控但代价也很明显本地要有匹配的 Qt、zlib、CMake 工具链还要花几分钟处理各种环境变量。对大多数 C/Qt 应用开发来说压缩解压只是附属功能不值得为它搭一整条编译链。这也是预编译库资源的价值所在。人家已经把工具链的坑趟平了你只需要关心当前工程是 Qt5 还是 Qt6、MSVC 还是 MinGW、x86 还是 x64然后把对应那一份 lib、dll 拿出来接线。这份精力省下来可以去处理更重要的业务逻辑。3. 把预编译 QuaZip 库接进 Qt 工程三条接线方式与运行时 DLL 处理拿到预编译库以后第一个动作不是写代码而是核对版本。这一步做扎实了后面所有链接错误都能避免。我一般会把 quazip 相关文件统一放进工程下的3rdparty/quazip目录方便以后升级替换。3.1 动手之前核对四件事接入前先确认四组信息Qt 主版本号、编译器类型、目标位数、Debug/Release 模式。常见的确认方法是打开命令行跑qmake -v看 qmake 输出里的 Qt 版本再看 Qt 安装目录下的套件名称比如msvc2019_64就代表 MSVC 2019 64 位mingw_64代表 MinGW 64 位。至于 Debug/Release看路径里是debug还是release目录或者看文件名很多预编译库会在 debug 库文件名后面带d后缀。提示这四项里任何一项不一致都不建议继续往下接。运气好只是编译告警运气差就是第十九层链接错误。3.2 CMake 接线用 IMPORTED 目标把库导进工程CMake 工程接入预编译库最稳的方式不是直接link_directories而是把 quazip 定义成一个导入目标这样头文件、导入库、DLL 路径都能集中在一个地方管理add_library(quazip SHARED IMPORTED) set_target_properties(quazip PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/3rdparty/quazip/bin/quazip.dll IMPORTED_IMPLIB ${CMAKE_SOURCE_DIR}/3rdparty/quazip/lib/quazip.lib INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/3rdparty/quazip/include ) target_link_libraries(app PRIVATE quazip)说明IMPORTED_LOCATION指向运行时 DLLIMPORTED_IMPLIB指向链接用的导入库MSVC 下是quazip.libMinGW 下要改成libquazip.dll.a。INTERFACE_INCLUDE_DIRECTORIES指定 QuaZip 头文件目录这样依赖 quazip 的目标会自动带上 include 路径。这里只做了导入真正的 DLL 部署还要看 3.4 节。3.3 qmake 接线INCLUDEPATH 与 LIBS 的 Debug/Release 分支还在用.pro工程的 Qt 项目配置更直接但 Debug/Release 的库分支建议提前写好不然换模式编译时又得改一次INCLUDEPATH $$PWD/3rdparty/quazip/include CONFIG(debug, debug|release) { LIBS -L$$PWD/3rdparty/quazip/lib/debug -lquazip } else { LIBS -L$$PWD/3rdparty/quazip/lib/release -lquazip }说明-L指定库搜索路径-lquazip让链接器去找quazip.libMSVC或libquazip.dll.aMinGW。写成CONFIG(debug, debug|release)分支是为了让 qmake 自动选择对应模式下的库避免把 debug 库链到 release 工程里这种错位导致的链接报错非常难查。3.4 运行时quazip.dll 要待在 exe 旁边不只是链接完就没事链接通过只代表编译期完成程序运行时要加载quazip.dllWindows 下 DLL 的搜索顺序是程序所在目录、系统目录、PATH 环境变量。最常见的坑是链接时用.lib导入了但运行目录里没有quazip.dll程序启动瞬间报“找不到 quazip.dll”。Qt 自带一个部署工具windeployqt可以帮你把 Qt 相关 DLL 全部复制到 exe 目录windeployqt --release --no-translations app.exe但要注意windeployqt只处理 Qt 自身的依赖QuaZip 不是 Qt 官方插件它不会自动复制quazip.dll。如果这份预编译库是动态链接 zlib还要把zlib1.dll一并带过去。我一般在windeployqt之后手动补一句复制命令把3rdparty/quazip/bin下的所有 DLL 拷到构建输出目录。4. QuaZip 核心调用用 QuaZipFile 完成目录压缩、解压与分块读写预编译库接入工程只是第一步真正检验成果的是调用代码。QuaZip 的 API 设计得比裸 zlib 友好得多能让你像操作普通文件一样操作 zip 包内部的条目。4.1 对象模型QuaZip 是 zip 外壳QuaZipFile 是里面的文件句柄先理清两个核心类的关系。QuaZip代表一个 zip 归档文件负责打开、关闭、遍历归档内部的条目QuaZipFile则是归档内的单个文件句柄你可以把它当QFile一样读写。QuaZip打开时有三种模式mdCreate创建新归档mdUnzip读取现有归档mdAppend在已有归档上追加内容。写压缩代码时顺序是固定的先创建一个QuaZip对象打开为mdCreate再创建QuaZipFile用open方法开始一个新条目写入数据后关闭QuaZipFile继续下一个最后关闭QuaZip。4.2 压缩一个目录从零开始打包带路径前缀和中文名假设有一个本地目录D:/data/images你想把它完整打进一个 zip 包保留相对路径结构。下面这个函数实现了基本逻辑bool zipDirectory(const QString zipPath, const QString srcDir) { QuaZip zip(zipPath); if (!zip.open(QuaZip::mdCreate)) { return false; } QDirIterator it(srcDir, QDir::Files, QDirIterator::Subdirectories); while (it.hasNext()) { QString fullPath it.next(); QString relativePath QDir(srcDir).relativeFilePath(fullPath); relativePath.replace(\\, /); QuaZipFile zipFile(zip); if (!zipFile.open(QIODevice::WriteOnly, QuaZipNewInfo(relativePath, fullPath))) { zip.close(); return false; } QFile inFile(fullPath); inFile.open(QIODevice::ReadOnly); char buf[8192]; qint64 got; while ((got inFile.read(buf, sizeof(buf))) 0) { zipFile.write(buf, got); } zipFile.close(); inFile.close(); } zip.close(); return true; }说明QuaZipNewInfo(relativePath, fullPath)第一个参数是 zip 包内的路径第二个参数是本地文件路径用来读取文件修改时间写入 zip 头relativePath.replace(\\, /)是把 Windows 路径分隔符转成 zip 标准要求的斜杠。读取本地文件时用了 8KB 缓冲区循环写入而不是readAll()处理几十 MB 的文件时能避免一次性占用大量内存。4.3 解压 Zip 到目录按条目逐一落盘先检查 zip 条目冲突解压逻辑反过来走。先以mdUnzip打开归档拿到所有条目信息再逐个创建QuaZipFile读取内容bool unzipToDir(const QString zipPath, const QString destDir) { QuaZip zip(zipPath); if (!zip.open(QuaZip::mdUnzip)) { return false; } zip.setFileNameCodec(UTF-8); QListQuaZipFileInfo entries zip.getFileInfoList(); for (const QuaZipFileInfo entry : entries) { if (entry.name.endsWith(/)) { continue; } QString outPath QDir(destDir).filePath(entry.name); QFileInfo info(outPath); if (!QDir().mkpath(info.absolutePath())) { zip.close(); return false; } QuaZipFile zipFile(zip); if (!zipFile.open(QIODevice::ReadOnly, entry.name)) { zip.close(); return false; } QFile outFile(outPath); outFile.open(QIODevice::WriteOnly); outFile.write(zipFile.readAll()); zipFile.close(); outFile.close(); } zip.close(); return true; }说明getFileInfoList()返回归档内全部条目比逐条goToFirstFile()更适合需要预判目录结构的使用场景。entry.name.endsWith(/)是为了跳过目录条目这类条目在 zip 里只是标记没有实际文件内容。解压到本地前用mkpath确保父目录存在避免文件流打开失败。中文文件名需要调用setFileNameCodec(UTF-8)否则部分工具打出的 zip 包里的中文名会乱码。4.4 别一次 readAll 大文件分块写入避免内存翻车上面解压代码为了简洁用了readAll()如果你确认压缩包内都是小文件这样没问题。但如果要处理几十 MB 甚至上百 MB 的单个文件readAll()会把整个文件内容一次性加载进内存长时间运行的进程内存直接冲高。我在某个处理批量图片的项目里就吃过这个亏压缩包内单张图都挺大几十张图全部 readAll 后进程内存飙到 600 多 MB。后来改成统一的QuaZipFile::read循环分块写入内存占用降到 20 MB 以内才算正常。预编译库只是解决了链接问题代码里的资源管理还是得自己把关。5. 避坑QuaZip 预编译库在链接、部署与中文字符集上的五个典型问题接入 QuaZip 预编译库链接和运行阶段最容易出问题。下面是我在多个项目里反复遇到的五个场景每一条都按“现象、原因、解决”拆开讲希望能帮你少走一次弯。5.1 场景一LNK2038 检测到 _ITERATOR_DEBUG_LEVEL 不匹配现象MSVC 下链接时报一堆LNK2038提示_ITERATOR_DEBUG_LEVEL不匹配或者RuntimeLibrary不匹配整个链接过程直接终止。原因当前工程编译选项用的是/MDdDebug 模式动态运行时而你链的预编译库是 Release 模式编出来的用的是/MD。MSVC 对运行时库匹配检查得很严Debug/Release 混用就会触发。解决检查你选的库文件是不是debug目录下的那一份。大多数预编译包会区分quazip.lib和quazipd.libDebug 工程必须链quazipd.lib。如果确实没有 debug 版本可以在当前工程的预处理定义里加上_ITERATOR_DEBUG_LEVEL0但这样做只建议临时验证不适合长期交付。5.2 场景二运行时 0xc000007b程序无法正常启动现象程序构建成功双击 exe 弹出“应用程序无法正常启动 0xc000007b”点击确定后退出。原因这个错误码的含义是“无效映像格式”最常见的是 32 位/64 位混用。比如你编译的是 64 位程序但quazip.dll是 32 位或者quazip.dll是 64 位而它依赖的zlib1.dll是 32 位。解决用 Dependency Walker 或 dumpbin 查看quazip.dll和zlib1.dll的位数确保三者一致。也可以用最笨的办法手动检查预编译包目录名x64 的库专门放 x64 目录缺文件时优先从同目录补齐。5.3 场景三exe 报“无法定位程序输入点于动态链接库”现象程序运行时报“无法定位程序输入点 xxx 于动态链接库 quazip.dll”启动即失败。原因链接期用的导入库和运行期加载的 DLL 不是同一个文件。常见情况是你链接的是quazip.lib但quazip.dll是另一个版本生成的两者导出表对不上。解决确认工程用的IMPORTED_IMPLIB和IMPORTED_LOCATION指向同一个构建产物目录。我一般会把quazip.lib和quazip.dll放在同一个bin、同一个lib子目录里这样链接器和运行时的引用路径天然一致不会出现两个版本同时在工程里的尴尬。5.4 场景四Qt platform plugin 加载失败QuaZip 背了锅现象程序编译链接全部正常发布到新机器后运行报This application failed to start because no Qt platform plugin could be initialized。原因这不是 QuaZip 的问题而是整个 Qt 运行环境没部署完整。你在开发机上可能因为系统 PATH 指向了 Qt 安装目录而一切正常但发布目录里缺少 Qt 平台插件qwindows.dll程序启动时 Qt GUI 模块无法初始化。解决在构建输出目录跑一遍windeployqt app.exe。它会把 Qt 依赖、平台插件、运行库全部复制到位。之后再把quazip.dll和zlib1.dll手工补进同一个目录。习惯上我把这个步骤做到构建脚本里每次编译完自动执行。5.5 场景五压缩包里的中文文件名变成乱码现象用 QuaZip 压缩的文件在 Windows 资源管理器或第三方解压工具里打开中文名显示为乱码或者反过来别人打的 zip 包里中文名在你的程序里读出来是乱的。原因zip 标准早期用 CP437 编码文件名后来中文环境常用 GBK 或 UTF-8。QuaZip 默认按本地编码处理不设置字符集就会产生不一致。解决写入端统一设置zip.setFileNameCodec(UTF-8)读取端解压前也必须调用同样方法确保两边用的是同一套字符集。如果你要兼容老式 Windows 工具可能得改用GBK这点要根据业务场景定没有万能解。重要的是写入和读取必须用相同的 codec否则必乱。6. 更进一步用 QBuffer 在内存里生成 Zip 再快速校验很多场景下zip 包不需要真的落盘。比如你要把一批配置文本传给某个接口或者把内存中的多段日志打成压缩包再上传直接写临时文件再删既慢又容易留垃圾。QuaZip 的构造函数支持传入QIODevice*这意味着用QBuffer就能在内存里完成读写。QByteArray zipBytes; QBuffer buffer(zipBytes); buffer.open(QIODevice::ReadWrite); { QuaZip zip(buffer); if (!zip.open(QuaZip::mdCreate)) { return false; } QuaZipFile file(zip); file.open(QIODevice::WriteOnly, QuaZipNewInfo(QStringLiteral(config.txt))); file.write(keyvalue\n); file.close(); zip.close(); } buffer.close(); // 验证把刚生成的内存数据当 zip 重新读一遍 QBuffer checkBuffer(zipBytes); checkBuffer.open(QIODevice::ReadOnly); QuaZip zipIn(checkBuffer); zipIn.open(QuaZip::mdUnzip); zipIn.goToFirstFile(); QuaZipFile checkFile(zipIn); checkFile.open(QIODevice::ReadOnly); qDebug() checkFile.readAll();说明大括号的作用是控制QuaZip对象的生命周期确保它在buffer关闭前析构把最后的 zip 尾记录写完。QuaZip zip(buffer)直接接管 QBuffer 作为输出流所有 zip 数据最终落在zipBytes这个QByteArray里。验证环节把zipBytes重新包装成只读 QBuffer再按mdUnzip模式打开读取确认文档结构和内容都没问题。内存 zip 做法省去文件 IO但要注意一点如果zipBytes特别大内存占用和文件方式没有本质区别。对于 10 MB 以内的轻量数据这是很好的方案超过 100 MB 还是老老实实走磁盘避免一次性内存分配把程序拖垮。从那以后我每次接预编译库都会强制走一遍先用qmake -v记下 Qt 版本再对着 include/lib/bin 里的文件名核对编译器与位数最后在 Release 模式下用windeployqt清一遍依赖确认quazip.dll和zlib1.dll都在 exe 旁边。这套流程听着啰嗦却让我躲过了好几次深夜翻车的局面。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑