最可靠的ini解析方式是用std::ifstream逐行读取并手动解析:跳过注释与空行,trim首尾空白,识别[section]和key=value,注意等号位置及大小写处理,严格校验格式并记录解析统计。

用 std::ifstream 逐行读取 + 手动解析最可靠
INI 文件没有统一标准,第三方库(如 inih 或 SimpleIni)常因编译器差异、宽字符支持或内存模型问题出错。自己写一个轻量解析器反而更可控,尤其当配置项少、格式固定时。
关键不是“能不能读”,而是“怎么避免把注释当键值”“怎么跳过空行和缩进”“怎么处理带等号的值”。
- 用
std::getline()逐行读,别用operator>>—— 后者会跳过空白并截断含空格的值 - 每行先
trim()(手动实现:用find_first_not_of(" \t\r\n")和find_last_not_of(" \t\r\n")) - 跳过以
;或#开头的行(注释),也跳过空行 - 遇到
[section]就更新当前 section;遇到key = value就存入std::map<:string std::map std::string>></:string>
std::string::find('=') 前必须检查是否在注释之后
常见错误是直接找第一个 =,结果把 ; timeout = 30 当成有效键值对。实际要先跳过开头的空白和分号/井号。
- 先用
find_first_not_of(" \t")定位非空白起始位置 - 若该位置是
';'或'#',整行忽略 - 再从该位置开始找
'=',且确保它不在引号内(简单场景可忽略引号;若需支持,得手写状态机) - 分割 key/value 时,
value部分也要 trim —— 很多人只 trim key,导致port = 8080存成"8080 "
section 名称大小写敏感性由你决定,但必须显式声明
Windows 下 INI 默认不区分大小写,Linux 工具常区分。C++ 标准库没内置 case-insensitive map,所以你得选:
立即学习“C++免费学习笔记(深入)”;
- 统一转小写存 key 和 section(用
std::tolower遍历每个 char) - 或保留原样,查的时候手动转换比较 —— 别依赖
std::map的默认排序 - 注意:Unicode 不适用
std::tolower,纯 ASCII 配置才安全 - 如果项目已用
std::unordered_map,记得自定义哈希和比较函数,否则大小写不同就查不到
别自动创建缺失 section,也别静默丢弃非法行
看似省事的“容错逻辑”反而让调试变难。比如把 [db 当成 [db],或把 user:pass 当成 user = pass,后续访问时崩溃才暴露问题。
- 遇到无闭合括号的 section 行,直接报错并返回 false(或抛
std::runtime_error) - 遇到无等号的非 section 行,记录警告(用
std::cerr),但不停止解析 - 值中含换行?INI 规范不支持,直接截断或报错 —— 别尝试跨行拼接,那是 YAML 的事
- 路径传参建议用
const std::string&,避免 Windows 下L"config.ini"强转出错
真正麻烦的从来不是读文件,而是有人改了 INI 格式却没通知你——加一行日志输出实际解析到的 section 数和 key 总数,比任何文档都管用。










