资讯动态

AI-on-the-edge-device 中的 miniz 单文件压缩库:zlib/Deflate 兼容实现与 OTA 固件解压实战

发布时间:2026/9/16 15:37:54 来源:尧图企业网站定制
AI-on-the-edge-device 中的 miniz 单文件压缩库zlib/Deflate 兼容实现与 OTA 固件解压实战【免费下载链接】AI-on-the-edge-deviceEasy to use device for connecting old measuring units (water, power, gas, ...) to the digital world项目地址: https://gitcode.com/GitHub_Trending/ai/AI-on-the-edge-deviceMiniz 是一个以单个 C 源文件形式发布的、无损高性能数据压缩库完整实现了 zlibRFC 1950与 DeflateRFC 1951压缩格式标准并兼容 zlib 最常用的 API。在 AI-on-the-edge-device 项目中它被集成在jomjol_fileserver_ota组件内承担着 OTA 固件更新包与 Web 前端 HTML 资源的 ZIP 解压任务。阅读本文后你将掌握 miniz 的核心能力、API 分层结构与裁剪方式并能结合仓库源码理解它在嵌入式 ESP32 设备上的真实解压调用链。miniz 是什么单文件、双标准、零依赖的压缩库Miniz 的核心定位可以从 readme.md 的一句话概括一个 lossless无损、高性能的压缩库整个库就是一个源文件同时实现了 zlibRFC 1950与 DeflateRFC 1951两种压缩数据格式规范。它具备三个关键特性zlib API 兼容支持 zlib 库导出的最常用函数因此可以当作 zlib 的 drop-in 替代品已在 libpng、libzip 等多个开源项目中被验证完全独立的实现虽然是 API 兼容但代码是完全独立编写的因此不继承 zlib 的许可证要求miniz 本身为 MIT 许可超出 zlib 的能力还附带简单易用的 PNG 图像文件写入函数以及 ZIP 压缩包读取/写入/追加append操作 API覆盖了嵌入式与移动端开发常见的归档处理需求。在性能定位上miniz 的压缩速度被调校到与 zlib 相当的水平并额外提供了一款面向实时压缩场景的专用压缩器用于与 fastlz、minilzo 等实时压缩库对标。readme 中给出的实测口径是在 level 1 时miniz.c 的压缩率比 minilzo 好约 5–9%但速度慢约 35%在 level 2–9 区间miniz.c 在压缩率与速度上与 zlib 相比不落下风。特性全景从便携单文件到流式协程实现readme 详细列举了 miniz 的设计特性这些特性也正是它适合嵌入式项目的原因特性说明许可证MIT宽松可商用可移植性纯 C 编写的单源文件 单头文件库已在 GCC、clang、Visual Studio 下测试可裁剪性通过宏定义即可轻松裁剪、精简库的体积如MINIZ_NO_STDIO、MINIZ_NO_ARCHIVE_APISAPI 兼容是 zlib 最常用 API 的 drop-in 替代品性能定位填补了实时压缩器与 zlib 之间的“单线程性能 vs 压缩率”空白流式处理不是块式压缩器采用 coroutine 风格实现支持单字节逐字节调用zlib 风格 API低级 API 无堆分配低级压缩器tdefl与解压器tinfl的状态结构体可通过简单 memcpy 保存/恢复且完全不使用堆单函数解压器整个 inflater含可选的 zlib 头解析与 Adler-32 校验以单函数协程形式实现可独立提取为约 550 行的小文件miniz_tinfl.cZIP 归档提供相当完整但完全可选的 ZIP 压缩包操作与提取 API专为嵌入式、移动端、游戏开发中的常见问题设计readme 特别强调ZIP 归档 API 的复杂度被刻意控制为“只要再补充少量高层逻辑就足以写出一整个归档工具”不至于过度膨胀。仓库内的集成方式release 文件直取 CMake 注册miniz 官方推荐的使用方式是直接使用 release 页面发布的miniz.c/miniz.h文件对而仓库正是遵循这一方式的。文件 readme2.md 记录了集成决策该目录是对 miniz release 的直接提取direct extraction之所以不用 git submodule 方式引入是因为子模块方式会带来各种集成问题因此选择“按 readme 建议使用 release 文件”这一更简单的路径并额外补上了CMakeLists.txt与本 readme。在构建层面jomjol_fileserver_ota组件的 CMakeLists.txt 使用FILE(GLOB_RECURSE ...)将该目录下所有源文件纳入编译并把miniz目录加入INCLUDE_DIRSFILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*) idf_component_register(SRCS ${app_sources} INCLUDE_DIRS . ../../include miniz REQUIRES vfs esp_http_server app_update esp_http_client nvs_flash ...)因此项目中只需#include miniz.h即可直接调用全部 API。当前仓库携带的 miniz 版本为11.0.1定义于 miniz.h 的MZ_VERSION。实战主线miniz 在 OTA 固件更新中的 ZIP 解压调用链miniz 不是仓库中的“摆设依赖”而是 OTA 更新流程的底层支撑。它在 server_help.cpp 中被实际使用调用链完整覆盖了 ZIP 读取器的“初始化 → 遍历 → 逐文件提取 → 收尾”四个阶段。unzip_file通用 ZIP 解压函数unzip_fileserver_help.cpp展示了 miniz ZIP 读取 API 的标准用法mz_zip_archive zip_archive; memset(zip_archive, 0, sizeof(zip_archive)); if (!mz_zip_reader_init_file(zip_archive, _in_zip_file.c_str(), 0)) { LogFile.WriteToFile(ESP_LOG_ERROR, TAG, mz_zip_reader_init_file() failed!); return; } int numberoffiles (int)mz_zip_reader_get_num_files(zip_archive); for (int i 0; i numberoffiles; i) { mz_zip_archive_file_stat file_stat; if (!mz_zip_reader_file_stat(zip_archive, i, file_stat)) continue; if (file_stat.m_is_directory) continue; std::string out_file _target_directory std::string(file_stat.m_filename); bool ok unzip_extract_file(zip_archive, i, out_file, file_stat); ... } mz_zip_reader_end(zip_archive);关键 API 与流程一一对应mz_zip_reader_init_file()从文件初始化 ZIP 读取器mz_zip_reader_get_num_files()获取归档内的文件总数mz_zip_reader_file_stat()逐条获取文件的元数据文件名、是否为目录、压缩前后大小等unzip_extract_file()内部调用mz_zip_reader_extract_to_callback()通过回调把解压数据写出mz_zip_reader_end()释放读取器资源。其中unzip_extract_fileserver_help.cpp把 miniz 的“回调式提取”与文件写入结合它先以wb模式打开输出文件再通过mz_zip_reader_extract_to_callback()将解压数据交给unzip_write_callback内部就是一次fwrite从而把“解压”与“落盘”彻底解耦——这正是嵌入式场景下控制内存占用的经典手法。unzip_firmwareOTA 固件包的定向解压面向 OTA 的unzip_firmwareserver_help.cpp在通用解压基础上加入了业务路由逻辑它遍历固件包内每个文件FIRMWARE.BIN被解压到目标 bin 目录并作为返回值标记固件路径config-initial目录在非首次安装_initial_setup false时被跳过普通 HTML 资源先解压到临时目录再通过RenameFile原子替换正式文件。整个过程完全复用 miniz 的mz_zip_reader_*系列 API。这两个函数的调用点位于 server_ota.cpp第 76 行OTA 升级时调用unzip_firmware(_file_name_update, outHtmlTmp /, outHtml /, outbin /, /sdcard/, initial_setup)解压固件包并把 HTML 资源、配置文件、固件 bin 分别落地到 SD 卡对应目录第 448 行调用unzip_file(in, out /)执行通用 ZIP 解压。也就是说当用户通过 Web 界面上传一个包含新固件与新版 Web 资源的压缩包时miniz 在 ESP32 设备端负责把整个包解压出来为后续的app_update刷写提供 bin 文件。这与 readme 中“ZIP 归档 API 专为嵌入式、移动端、游戏开发常见问题设计”的定位完全吻合。API 三层结构zlib 兼容层、低级 tdefl/tinfl、ZIP/PNG 高层miniz 的 API 设计分三个层次readme 与随附的 6 个示例见 examples 目录正好一一对应1. zlib 兼容层compress / uncompress / deflate / inflateexample1.c 演示了与 zlib 同名的compress()/uncompress()用法可直接作为 zlib 迁移的起点cmp_status compress(pCmp, cmp_len, (const unsigned char *)s_pStr, src_len); ... cmp_status uncompress(pUncomp, uncomp_len, pCmp, cmp_len);example3.c 则展示deflate()/inflate()的文件压缩场景示例限定文件小于 4GB但这是示例本身的限制并非 miniz 的限制。2. 低级 tdefl/tinfl 层最快、零堆分配、最灵活example5.c 演示了低级 API 的文件到文件压缩/解压。这一层是 miniz 性能与可控性的核心压缩器状态tdefl_compressor是一个较大的结构体约 300KB注释明确说明因此示例将其声明为全局变量而非栈上变量压缩通过tdefl_init()tdefl_compress()循环驱动配合TDEFL_NO_FLUSH/TDEFL_FINISH控制流结束TDEFL_WRITE_ZLIB_HEADER标志用于写出 zlib 头解压通过tinfl_init()tinfl_decompress()循环驱动TINFL_FLAG_PARSE_ZLIB_HEADER与TINFL_FLAG_HAS_MORE_INPUT分别控制 zlib 头解析与“输入未完”语义压缩级别-l[0-10]直接映射到字典探测次数表s_tdefl_num_probes[11]0/1/6/32/16/32/128/256/512/768/15000表示最快、最少探测配合TDEFL_FORCE_ALL_RAW_BLOCKS可实现“无压缩”模式示例文件头部通过#define MINIZ_NO_STDIO / MINIZ_NO_ARCHIVE_APIS / MINIZ_NO_TIME / MINIZ_NO_ZLIB_APIS / MINIZ_NO_MALLOC裁剪掉所有不需要的功能——这是 readme 所说“easily tuned and trimmed down by defines”的直接例证。example4.c 则演示了tinfl_decompress_mem_to_callback()这种“内存解压到回调”的便捷路径。3. ZIP 归档层读写/追加 PNG 写入example2.c 演示了完整的 ZIP 写入与读取流程用mz_zip_add_mem_to_archive_file_in_place()在现有归档中追加文件这是“append”能力的体现随后用mz_zip_reader_init_file()mz_zip_reader_get_num_files()mz_zip_reader_file_stat()mz_zip_reader_extract_file_to_heap()读回并校验。MZ_BEST_COMPRESSION与MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY等标志在示例中均有出现。PNG 写入能力则由 example6.cMandelbrot 图像生成演示对应defl_write_image_to_png_file_in_memory_ex()系列函数。仓库中 OTA 解压正是选择了ZIP 归档层 回调式提取的组合这说明高层 API 在嵌入式上的实用性而低级层则适合需要极致控制、避免堆分配的实时场景。构建与获取方式vcpkg 与直接拷贝readme 给出的构建方式有三类直接使用 release 文件从 releases 页面下载miniz.c/miniz.h文件对直接加入工程本仓库采用的方式。这一文件对由不同源码/头文件在构建期amalgamated合并而成与 SQLite 的合并发布方式同源作为 CMake 或 meson 模块引入或使用其他构建系统vcpkg 包管理器安装git clone https://github.com/Microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.sh ./vcpkg integrate install ./vcpkg install minizreadme 同时说明vcpkg 中的 miniz 端口由 Microsoft 团队成员与社区贡献者维护更新若版本滞后可向 vcpkg 仓库提交 issue 或 pull request。已知问题与边界readme 明确列出的已知限制需要在使用前知晓不支持加密压缩包encrypted archives作者对此的直接评价是“不确定这东西在实践中有多大用处”文档偏少作者假定用户已熟悉 zlib 基础 API因此将关键注释放在每个枚举/API 之前并提供了 6 个示例覆盖主要功能但完整 API wiki 尚待编写。许可与专利说明许可miniz 采用 MIT 许可自 vogl 的 ZIP64 代码合并后可自由商用与修改专利miniz 刻意使用与 zlib 相同的核心算法——压缩器使用 RFC 1951 第 4 节所述的 vanilla hash chaining 方案。作者的观点是如果 miniz 遭遇专利攻击那么 zlib/gzip 同样面临严重风险因此该风险是行业共担而非 miniz 特有。小结miniz 以“单文件、双标准RFC 1950/1951、zlib 兼容、可选 ZIP/PNG”四个关键词构成了一个对嵌入式极其友好的压缩方案。在 AI-on-the-edge-device 中它通过 server_help.cpp 的unzip_file/unzip_firmware函数深度参与 OTA 固件更新流程是设备端“上传压缩包 → 解压固件与 Web 资源 → 刷写/替换”链条中不可缺失的一环。若你想进一步研究其实现细节可阅读 miniz.h 中 API 前的关键注释、miniz.c 的合并源码以及 ChangeLog.md 了解各版本的 bug 修复与演进脉络。【免费下载链接】AI-on-the-edge-deviceEasy to use device for connecting old measuring units (water, power, gas, ...) to the digital world项目地址: https://gitcode.com/GitHub_Trending/ai/AI-on-the-edge-device创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

免费获取报价