在C++开发中,解析INI配置文件是一项常见需求。INI文件通常由若干节(section)组成,每个节下面包含多个键值对,用来保存程序配置。我们可以通过标准库中的文件操作和字符串处理,自己写一个简单工具来完成配置项的读取与解析,而不必引入庞大的第三方库。

INI文件的基本结构
一个典型的INI文件内容如下,其中用中括号包裹的是节名称,节下方是键等于值的配置行:
[server] host=127.0.0.1 port=8080 [log] level=info path=./app.log
核心解析思路
我们的解析工具主要做三件事:打开文件并逐行读取;识别节名称;将键值对保存到内存结构中。可以使用std::map嵌套来保存节和对应的键值。
数据结构设计
用外层map的key表示节名,内层map的key表示配置项名称,value就是配置值:
#include <map> #include <string> // 节名 -> (键名 -> 值) typedef std::map<std::string, std::map<std::string, std::string>> IniData;
读取与解析实现
下面给出一个简单的解析函数示例,它能处理节头和键值对,并忽略空行与注释(以分号开头):
#include <fstream>
#include <iostream>
#include <sstream>
#include <algorithm>
IniData parse_ini(const std::string& filepath) {
IniData data;
std::ifstream file(filepath);
if (!file.is_open()) {
std::cerr << "无法打开文件: " << filepath << std::endl;
return data;
}
std::string line;
std::string current_section;
while (std::getline(file, line)) {
// 去掉首尾空格
line.erase(0, line.find_first_not_of(" t"));
line.erase(line.find_last_not_of(" t") + 1);
if (line.empty() || line[0] == ';') {
continue;
}
if (line[0] == '[') {
size_t end = line.find(']');
if (end != std::string::npos) {
current_section = line.substr(1, end - 1);
}
continue;
}
size_t eq_pos = line.find('=');
if (eq_pos != std::string::npos) {
std::string key = line.substr(0, eq_pos);
std::string value = line.substr(eq_pos + 1);
key.erase(0, key.find_first_not_of(" t"));
key.erase(key.find_last_not_of(" t") + 1);
value.erase(0, value.find_first_not_of(" t"));
value.erase(value.find_last_not_of(" t") + 1);
data[current_section][key] = value;
}
}
return data;
}如何使用解析结果
解析完成后,我们可以很方便地通过节名和键名获取对应的配置值:
int main() {
IniData cfg = parse_ini("config.ini");
std::string host = cfg["server"]["host"];
std::string port = cfg["server"]["port"];
std::cout << "连接 " << host << ":" << port << std::endl;
return 0;
}注意事项与扩展
- 上述代码未处理引号包裹的值,如需支持可额外去掉首尾双引号。
- 若配置项可能出现重复键,可改为保存vector结构。
- 对大小写敏感的场景,可统一将节名和键名转为小写再存储。
通过这种方式,我们用不到一百行C++代码就实现了一个基础的INI配置读取工具,能够满足多数小型项目的配置解析需要。