7z文件需用7-Zip SDK的C接口解析,因其采用LZMA压缩、多段流式结构及自定义头信息,libzip等标准ZIP工具无法识别;必须使用ISzInStream+CSzArEx组合,注意UTF-16文件名转换、PackStream偏移计算、内存缓冲区生命周期管理及Headers Encrypted标志检查。

7z文件不是普通ZIP,不能用libzip或miniz直接读
7z格式采用LZMA/LZMA2压缩、多段流式结构和自定义头信息,标准ZIP工具链完全无法识别其内部结构。试图用fopen读取后硬解析二进制头会失败——7z的Signature Header(0x19 0x4C 0x5A 0x49 0x50 0x37 0x7A 0xBC)之后紧跟的是可变长的Header Stream,包含Encoded Header、Main Streams Info、Files Info等嵌套结构,手动解析极易出错。
- libarchive虽支持7z解包,但不暴露原始结构(如每个文件的压缩方法、块偏移、CRC校验位置)
- Boost.Iostreams无原生7z backend,需自行绑定7z SDK
- Python的py7zr底层调用的是7z SDK,C++中直接对接更可控
必须用7-Zip SDK的C接口(C++封装层太薄)
官方7-Zip SDK提供纯C函数集,C++项目应直接链接7z.dll(Windows)或lib7z.so(Linux),避免用C++ wrapper(如cpp7z)——它们常滞后于SDK更新,且对Header解析支持不全。关键入口是ISzInStream + CSzArEx组合,而非IInArchive(后者只用于解压,不暴露结构细节)。
- 初始化时必须调用
SzArEx_Init(&g_Ar),否则SzArEx_Extract会崩溃 - 获取文件列表用
g_Ar.NumFiles和g_Ar.FileNames,但注意:文件名是UTF-16编码,需转为UTF-8 - 每个文件的压缩属性(如
IsDir、CrcDefined、Crc)存在g_Ar.CRCs.Vals数组中,索引与g_Ar.FileIndexToFolder映射
解析文件块偏移需遍历Folder和PackStream
7z中一个“文件”可能跨多个Pack Stream(压缩数据块),真实存储位置由g_Ar.Folders和g_Ar.PackPos共同决定。仅靠g_Ar.UnpackSize无法定位原始压缩数据起始地址——必须计算g_Ar.PackPos[folderIndex] + 对应Folder内SubStream的偏移。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 调用
SzArEx_GetFolderStreamPos(&g_Ar, folderIndex, 0)获取该Folder第一个Pack Stream的全局偏移 - 用
SzArEx_GetNumFilesInFolder(&g_Ar, folderIndex)确认该Folder包含几个文件 - 若文件被分卷(Split),
g_Ar.FileIndexToFolder会出现重复folderIndex,此时需结合g_Ar.FolderToFile查实际映射
内存解压时务必检查lookStream->buf生命周期
SDK默认使用回调式IO(ISzInStream),若用内存加载7z文件,必须确保传入的lookStream->buf在SzArEx_Extract全程有效。常见错误是把std::vector<uint8_t></uint8_t>局部变量地址传给lookStream,导致extract中途访问野指针。
立即学习“C++免费学习笔记(深入)”;
- 正确做法:将7z文件完整读入
static std::vector<uint8_t> g_7zData</uint8_t>,再令lookStream->buf = g_7zData.data() - 不要依赖
SzArEx_Extract返回的*outBuffer直接当原始压缩数据——它已是解压后内容;若要原始压缩流,需自己从g_Ar.PackPos处memcpy - Windows下DLL加载失败时错误码是
ERROR_MOD_NOT_FOUND,不是ENOENT,别用perror打印
Header结构里最易被忽略的是“Headers Encrypted”标志位(位于Header Stream末尾),如果7z文件启用了头加密(非内容加密),SzArEx_Open会静默失败且不报错,必须先用LookInStream_Seek跳到末尾检查该字节。

















