windows .ini文件需手写解析,用fgets/std::getline逐行读取并切分,以std::map存储,注意trim空格、编码兼容、安全访问及数值转换。

Windows .ini 文件没有标准 C++ 库支持,必须手写解析逻辑;直接用 fgets + 字符串切分是最轻量、最可控的方式,比引入 Boost.PropertyTree 或 INIReader 第三方库更适配“简易”需求。
INI 文件的结构特征决定了不能用通用配置解析器
典型的 Windows .ini 文件是纯文本,格式固定:以 [section] 开头的节,其后每行是 key=value(允许空格、注释以 ; 或 # 开头),不嵌套、无类型、无转义(除个别旧版扩展外)。这意味着:
- 不需要 JSON/YAML 那类递归解析器,也无需处理引号或 Unicode 转义
-
std::getline逐行读取 +std::string::find/std::string::substr切分足够可靠 - 注意:Windows API 的
GetPrivateProfileString虽可用,但仅限 ANSI 编码、不支持 UTF-8、且在非 Windows 平台不可用,跨平台项目应避免
用 std::map<:string std::map std::string>></:string> 存储解析结果
这是最直观的内存结构:外层 key 是 section 名,内层 key 是属性名,value 是字符串值。示例代码片段:
std::map<:string std::map std::string>> ini;
std::string line, section;
std::ifstream file("config.ini");
while (std::getline(file, line)) {
// 去首尾空格
auto trim = [](const std::string& s) -> std::string {
size_t b = s.find_first_not_of("
");
size_t e = s.find_last_not_of("
");
return (b == std::string::npos) ? "" : s.substr(b, e - b + 1);
};
line = trim(line);
if (line.empty() || line[0] == ';' || line[0] == '#') continue;
if (line[0] == '[' && line.back() == ']') {
section = trim(line.substr(1, line.length() - 2));
continue;
}
size_t eq = line.find('=');
if (eq != std::string::npos) {
std::string key = trim(line.substr(0, eq));
std::string val = trim(line.substr(eq + 1));
ini[section][key] = val;
}
}
</:string>
关键点:
- 必须手动 trim 空格,否则
"key = value"会导致 key 变成"key " - 节名和键名区分大小写(Windows 默认不区分,但 C++ 解析器默认区分;如需兼容,统一转小写再存)
- 不处理反斜杠续行、双引号包裹值等非经典用法——它们不属于“经典 .ini”规范
读取时常见错误:编码与换行符
Windows 上的 .ini 文件通常是 ANSI(即系统本地编码,如 GBK)或 UTF-8(无 BOM)。C++ std::ifstream 默认按字节读取,不自动识别编码:
- 若文件含中文且为 GBK 编码,用 UTF-8 编译的程序读出来就是乱码——此时应改用
std::wifstream+std::locale绑定 codepage(如936),或提前转 UTF-8 - 换行符为
,std::getline默认按切割,会把留在行末——这就是为什么必须做 trim - 不要用
file >> line,它遇空格就停,无法读完整行
获取值时的健壮性检查不能省
调用方代码很容易写成 ini["network"]["port"],但若 section 或 key 不存在,会触发隐式插入空 map/空 string,掩盖配置缺失问题:
- 封装一个安全访问函数,例如:
get_value(ini, "network", "port", "8080"),内部用find()判断是否存在 - 数值转换(如 int、bool)必须单独做,
std::stoi遇非法字符串会抛异常,建议用std::from_chars(C++17)或strtol检查endptr - 路径类值(如
log_path=C:pplog)中的反斜杠不用转义——.ini 是纯文本,C:\app\log是用户写错了,不是你代码要修的
真正麻烦的从来不是语法解析,而是用户把注释写在等号后面、把空格塞进键名、或者用记事本另存为 UTF-8 with BOM——这些细节比算法本身更消耗调试时间。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











