xlnt和openxlsx不支持.xls格式,因其仅识别.xlsx的zip头(50 4b 03 04),而.xls是biff二进制格式,文件头为d0 cf 11 e0(ole复合文档);libxls读取易段错误因结构体未memset清零致野指针,且不区分空/未定义单元格,需按row->cells.count遍历并检查cell->id类型,字符串须用std::string(cell->str, cell->str_len)构造后转码。

只能用 libxls,别试 xlnt 或 OpenXLSX —— 它们根本不认识 .xls 文件。
为什么 xlnt::workbook::load() 一读 .xls 就崩?
因为 xlnt 只处理 .xlsx(即 ZIP + XML 的 OpenXML 格式),而 .xls 是二进制 BIFF 格式,文件头是 D0 CF 11 E0 A1 B1 1A E1(OLE 复合文档),不是 50 4B 03 04(ZIP 头)。调用 load() 会直接抛 xlnt::exception,错误信息类似 "Invalid file signature" 或 "Not a valid ZIP archive"。
同理,OpenXLSX、libxlsxwriter、libxl 的免费版(注意:libxl 商用版才支持 .xls)也都无法加载 .xls —— 不是配置问题,是格式层面的不兼容。
libxls 读取时为什么会段错误在 xls_getCell()?
libxls 是纯 C 库,不自动初始化结构体字段。如果你声明了 XLSTABLE* table 或 XLSWORKBOOK* wb 却没 memset 清零,里面指针字段就是野值,xls_getCell() 一解引用就段错误。
- 必须在
xls_open_file()前对返回指针做空检查:if (!wb) { /* error: check error param */ } - 必须调用
xls_parseWorkSheet()—— 不调它,work_sheet->rows里全是未初始化垃圾,遍历必崩 - 遍历列不能写
for (int k = 0; k lastcol; k++):Excel 允许稀疏列(比如第 3 列有数据、第 4 列隐藏、第 5 列又有数据),实际有效单元格数得看row->cells.count - 每个
cell要先判cell->id类型:XLS_RECORD_STRING、XLS_RECORD_NUMBER、XLS_RECORD_BLANK等,不能默认当字符串取
字符串显示为空或乱码,真是内容为空吗?
不是。libxls 把 Excel 内部原始字节流原样暴露,不做任何编码转换。如果文件是 GBK 编码保存的,你用 std::cout str 输出,就会乱码或截断 —— 因为 cell->str 是 char*,长度由 cell->str_len 给出,且不含终止符,还可能含 Excel 填充的 \0 字节。
- 安全做法:用
std::string(cell->str, cell->str_len)构造,再按需转码(如用 iconv 或 Windows API 转 UTF-8) - 传给
xls_open_file()的编码参数(如"UTF-8")只影响工作表名等元数据,不影响单元格内容 - 别用
printf("%s", cell->str)—— 遇到内部\0就提前结束
最易被忽略的一点:libxls 不区分「空单元格」和「未定义单元格」。同一行中若中间跳过一列,row->cells 数组里根本不会占位,下标不连续 —— 你必须依赖 row->cells.count 和每个 cell->col 字段来还原真实列位置,而不是靠数组索引推算。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











