用std::ifstream手动解析INI文件最直接,需逐行读取、处理注释/空行/节名/键值对,注意\r清理、大小写处理、默认节及编码问题。

用 std::ifstream 手动解析 INI 文件最直接
INI 文件本质是纯文本,没有标准库支持,C++ 里最轻量、最可控的方式就是自己读行、切分、跳过注释和空行。不需要引入第三方库,适合嵌入式或极简项目。
关键点在于:INI 的节([section])和键值对(key=value)都有固定格式,但容错性差——比如等号前后有空格、值含 # 号、引号包裹、反斜杠转义等,都得自己处理。
- 用
std::getline()逐行读取,跳过以;或#开头的注释行和空行 - 遇到
[section_name]时提取节名,后续所有键值对归属该节 - 对普通行用
find('=')找第一个等号,左侧 trim 后为 key,右侧 trim 后为 value - 注意:Windows 换行符是
\r\n,Linux 是\n,std::getline()默认按\n切分,\r会残留在字符串末尾,务必用erase(remove(...))清掉
封装成 IniParser 类管理 section 和 key-value 映射
手动解析一次后,数据散在多个变量里很难复用。推荐用 std::map<:string std::map std::string>> 存储:外层 key 是 section 名,内层是 key-value 对。这样查配置就像 ini["network"]["port"] 一样自然。
常见坑:
立即学习“C++免费学习笔记(深入)”;
- section 名区分大小写,但很多实际 INI(尤其 Windows 工具生成的)默认不区分,建议统一转小写再存
- 同一个 key 在同一 section 出现多次时,后出现的会覆盖前一个——这是大多数解析器的行为,不是 bug
- 没声明 section 就直接写
key=value,应归入默认节(如"DEFAULT"),否则容易丢数据
class IniParser {
public:
std::map> data;
void parse(const std::string& filename) {
std::ifstream file(filename);
std::string line, current_section = "DEFAULT";
while (std::getline(file, line)) {
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
if (line.empty() || line[0] == ';' || line[0] == '#') continue;
if (line[0] == '[' && line.find(']') != std::string::npos) {
current_section = line.substr(1, line.find(']') - 1);
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));
data[current_section][key] = val;
}
}
}private:
std::string trim(const std::string& s) {
size_t l = s.find_first_not_of(" \t");
size_t r = s.find_last_not_of(" \t");
return (l == std::string::npos) ? "" : s.substr(l, r - l + 1);
}
};
用 std::stoi/std::stof 安全转换数值类型
INI 里的值全是字符串,业务代码里常要转成 int、float、bool。别直接用 atoi 或 atof——它们遇到非法输入返回 0,无法区分“真就是 0”和“解析失败”。
正确做法是用 std::stoi 等,并捕获 std::invalid_argument 和 std::out_of_range 异常:
-
bool 建议约定值为 "true"/"false" 或 "1"/"0",不要依赖字符串非空即 true
- 整数溢出时
std::stoi 抛 std::out_of_range,比静默截断安全得多
- 如果某配置项缺失,应提供默认值,而不是让程序崩溃;可用
data[section].count(key) 先判断是否存在
跨平台路径与编码问题不能忽略
Windows 上记事本保存的 INI 文件默认是 GBK 编码,而 C++ 标准流在 Linux/macOS 下默认按 UTF-8 解析。如果文件含中文,std::ifstream 会读成乱码——这不是解析逻辑的问题,是编码层就错了。
解决方式有限:
- 强制要求配置文件保存为 UTF-8 无 BOM(推荐,VS Code、Notepad++ 都可设)
- Windows 下可用
std::wifstream + imbue 设置本地 locale,但移植性差
- 更稳妥的做法是:先用系统 API(如 Windows 的
MultiByteToWideChar)或轻量库(如 utf8cpp)做预转换,再喂给解析器
- 路径分隔符也需注意:
"config\settings.ini" 在 Linux 下打不开,应统一用 / 或 std::filesystem::path 拼接
真正麻烦的从来不是怎么切等号,而是没人告诉你:那个看似正常的中文配置项,其实从打开文件那一刻起就已经是乱码了。











