SimpleIni 是一个跨平台的 C++ 库,支持Windows, WinCE and Linux系统,提供一个简单的API用于操作 ini 配置文件。
simpleini项目地址:
https://github.com/brofield/simpleini
一、Simpleini Api
1. 初始化和加载/保存文件
// 使用窄字符版本 (char/UTF-8)
CSimpleIniA ini;
ini.SetUnicode(true); // 启用 Unicode 支持
// 使用宽字符版本 (wchar_t)
CSimpleIniW iniW;
// 加载 INI 文件
SI_Error rc = ini.LoadFile("config.ini");
if (rc < 0) { /* 处理错误 */ }
// 保存 INI 文件
rc = ini.SaveFile("config.ini");
2. 读写值
// 设置值
ini.SetValue("section", "key", "value");
// 获取值(带默认值)
const char* value = ini.GetValue("section", "key", "default_value");
// 获取数值类型
long nValue = ini.GetLongValue("section", "key", 0);
double dValue = ini.GetDoubleValue("section", "key", 0.0);
bool bValue = ini.GetBoolValue("section", "key", false);
// 设置数值类型
ini.SetLongValue("section", "key", 42);
ini.SetDoubleValue("section", "key", 3.14);
ini.SetBoolValue("section", "key", true);
3. 节(Section)操作
// 获取所有节
CSimpleIniA::TNamesDepend sections;
ini.GetAllSections(sections);
// 检查节是否存在
bool bExists = ini.GetSectionSize("section") > 0;
// 删除节(及其所有键)
ini.Delete("section", NULL);
4. 键(Key)操作
// 获取节中所有键
CSimpleIniA::TNamesDepend keys;
ini.GetAllKeys("section", keys);
// 检查键是否存在
bool bExists = ini.KeyExists("section", "key");
// 删除键
ini.Delete("section", "key");
高级功能
1. 多值键
// 添加多个值(不覆盖现有值)
ini.SetValue("section", "key", "value1", false);
ini.SetValue("section", "key", "value2", false);
// 获取所有值
CSimpleIniA::TNamesDepend values;
ini.GetAllValues("section", "key", values);
2. 注释
// 设置节注释
ini.SetSectionComment("section", "这是节的注释");
// 设置键注释
ini.SetKeyComment("section", "key", "这是键的注释");
// 获取注释
const char* comment = ini.GetSectionComment("section");
comment = ini.GetKeyComment("section", "key");
3. 数据类型转换
// 从字符串转换
long lVal;
ini.GetValue("section", "key", "0", &lVal);
double dVal;
ini.GetValue("section", "key", "0.0", &dVal);
bool bVal;
ini.GetValue("section", "key", "false", &bVal);
4.存储uint类型, 读取uint类型
在 CSimpleIniA 中存储和读取 uint
(无符号整型)类型,你需要进行字符串转换。
#include "SimpleIni.h"
#include <iostream>
#include <string>
#include <sstream>
int main() {
CSimpleIniA ini;
ini.SetUnicode();
// 写入 uint 值
unsigned int writeValue = 123456789;
std::stringstream writeSS;
writeSS << writeValue;
ini.SetValue("TEST", "UIntValue", writeSS.str().c_str());
ini.SaveFile("test.ini");
// 读取 uint 值
ini.LoadFile("test.ini");
const char* strValue = ini.GetValue("TEST", "UIntValue", "0");
unsigned int readValue;
std::stringstream readSS(strValue);
readSS >> readValue;
std::cout << "写入的值: " << writeValue << std::endl;
std::cout << "读取的值: " << readValue << std::endl;
return 0;
}
为了方便使用,你可以创建辅助函数:
#include "SimpleIni.h"
#include <string>
#include <sstream>
// 写入 uint 值
bool WriteUIntToIni(CSimpleIniA& ini, const char* section,
const char* key, unsigned int value) {
std::stringstream ss;
ss << value;
return ini.SetValue(section, key, ss.str().c_str()) == SI_OK;
}
// 读取 uint 值
unsigned int ReadUIntFromIni(CSimpleIniA& ini, const char* section,
const char* key, unsigned int defaultValue = 0) {
const char* strValue = ini.GetValue(section, key, nullptr);
if (!strValue) return defaultValue;
try {
return std::stoul(strValue);
} catch (...) {
return defaultValue;
}
}
// 使用示例
CSimpleIniA ini;
ini.SetUnicode();
ini.LoadFile("config.ini");
// 写入
WriteUIntToIni(ini, "Settings", "Timeout", 5000);
// 读取
unsigned int timeout = ReadUIntFromIni(ini, "Settings", "Timeout", 1000);
实用工具函数
// 检查是否已修改
bool bModified = ini.IsModified();
// 重置修改状态
ini.ResetModified();
// 清空所有数据
ini.Reset();
字符转义处理
在 INI 文件和 SimpleIni 库中使用特殊字符时,正确处理字符转义非常重要。以下是详细的转义处理方法和最佳实践。
1. 需要转义的关键字符
字符 | 说明 | 是否需要转义 |
---|---|---|
= | 键值分隔符 | 值(value)中出现时需要 |
; | 注释标识符 | 值中出现时需要 |
# | 替代注释符 | 值中出现时需要 |
\ | 转义字符本身 | 总是需要转义 |
[ 和 ] | 节(section)标识符 | 节名和值中出现时需要 |
\n | 换行符 | 需要特殊处理 |
转义处理方法
1. 手动转义方法
std::string EscapeIniValue(const std::string& value) {
std::string escaped;
for (char c : value) {
switch (c) {
case '=':
case ';':
case '#':
case '[':
case ']':
case '\\':
escaped += '\\'; // 添加转义字符
// 继续执行default
default:
escaped += c;
}
}
return escaped;
}
std::string UnescapeIniValue(const std::string& value) {
std::string unescaped;
bool escape = false;
for (char c : value) {
if (escape) {
unescaped += c;
escape = false;
} else if (c == '\\') {
escape = true;
} else {
unescaped += c;
}
}
return unescaped;
}
2. 使用 SimpleIni 内置功能
SimpleIni 会自动处理一些基本的转义:
CSimpleIniA ini;
ini.SetUnicode(true);
// SimpleIni 会自动处理值中的等号
ini.SetValue("Section", "Key", "value=with=equals");
// 但注释符号需要手动处理
ini.SetValue("Section", "Comment", EscapeIniValue("value;with;comment"));
路径和URL处理
1. Windows路径转义
std::string path = "C:\\Program Files\\App\\config.ini";
std::string escapedPath = EscapeIniValue(path);
ini.SetValue("Paths", "Config", escapedPath.c_str());
2. URL参数处理
std::string url = "https://example.com?param1=value1¶m2=value2";
std::string escapedUrl = EscapeIniValue(url);
ini.SetValue("Web", "Endpoint", escapedUrl.c_str());
二、基本实例
创建test.ini文件,内容如下:
[server]
root = 10.1.1.1
gc = 10.1.1.2
game = 10.1.1.3
#include <iostream>
#include <SimpleIni.h>
using namespace std;
int main()
{
CSimpleIniA ini;
ini.SetUnicode();
ini.LoadFile("test.ini");
const char * pVal = ini.GetValue("server", "game", "default");
ini.SetValue("server", "game", "10.1.1.5");
const char * xVal = ini.GetValue("server", "game", "default");
cout << pVal << endl;
cout << xVal << endl;
// save the data back to the file
int rc = ini.SaveFile("test.ini");
if (rc < 0) return false;
}
三、使用 SimpleIni 操作中文
SimpleIni 是一个跨平台的 C++ 库,用于读写 INI 格式的配置文件。要正确处理中文 UTF-8。对于使用 SimpleIni 库处理中文或其他非ASCII字符的情况,.ini 文件应当保存为 UTF-8 格式(无BOM)。
为什么推荐 UTF-8
-
跨平台兼容性:UTF-8 是跨平台最通用的 Unicode 编码格式。
-
中文支持:可以完美支持中文及其他多语言字符。
-
与 SimpleIni 配合:SimpleIni 的
SetUnicode(true)
就是为 UTF-8 设计的。
基本用法(支持 UTF-8)
#include "SimpleIni.h"
#include <iostream>
int main() {
CSimpleIniA ini;
ini.SetUnicode(true);
// 加载或创建文件
SI_Error rc = ini.LoadFile("config.ini");
if (rc < 0) {
std::cerr << "无法加载文件,将创建新文件" << std::endl;
}
// 设置值
ini.SetValue("用户", "姓名", "张三");
ini.SetLongValue("用户", "年龄", 25);
ini.SetBoolValue("设置", "启用", true);
// 添加注释
ini.SetSectionComment("用户", "用户信息部分");
ini.SetKeyComment("用户", "姓名", "用户的真实姓名");
// 保存
rc = ini.SaveFile("config.ini");
if (rc < 0) {
std::cerr << "保存文件失败" << std::endl;
return 1;
}
// 读取
const char* name = ini.GetValue("用户", "姓名", "");
int age = ini.GetLongValue("用户", "年龄", 0);
bool enabled = ini.GetBoolValue("设置", "启用", false);
std::cout << "姓名: " << name << "\n"
<< "年龄: " << age << "\n"
<< "启用: " << (enabled ? "是" : "否") << std::endl;
return 0;
}
注意事项
-
字符集设置:
-
使用
CSimpleIniA
并调用SetUnicode(true)
来正确处理 UTF-8 -
或者直接使用
CSimpleIniW
来处理宽字符
-
-
文件编码:
-
确保源文件保存为 UTF-8 编码(无 BOM)
-
确保编辑器使用 UTF-8 编码保存配置文件
-
-
跨平台问题:
-
在 Windows 上可能需要特别注意编码转换
-
Linux/macOS 通常默认使用 UTF-8,问题较少
-
SimpleIni 库操作中文并写入文件时,建议将内容转换为 UTF-8 存储,以确保中文字符能正确保存和读取。
(1)使用 UTF-8 模式
#include "SimpleIni.h"
#include <QString>
CSimpleIniA ini;
ini.SetUnicode(true); // 启用 UTF-8 支持
QString key = "姓名";
QString value = "张三";
// 写入时转成 UTF-8
ini.SetValue("Section", key.toUtf8().constData(), value.toUtf8().constData());
// 保存文件
ini.SaveFile("config.ini");
(2)读取时也要用 UTF-8
CSimpleIniA ini;
ini.SetUnicode(true);
ini.LoadFile("config.ini");
QString key = "姓名";
const char* value = ini.GetValue("Section", key.toUtf8().constData(), "");
// 转回 QString
QString result = QString::fromUtf8(value);
宽字符版本示例 (CSimpleIniW)
#include "SimpleIni.h"
#include <iostream>
int main() {
CSimpleIniW ini;
ini.SetUnicode(true);
// 设置中文值
ini.SetValue(L"section", L"key", L"中文内容");
// 保存文件
SI_Error rc = ini.SaveFile(L"config.ini");
if (rc < 0) {
std::wcerr << L"保存文件失败" << std::endl;
return 1;
}
// 读取文件
rc = ini.LoadFile(L"config.ini");
if (rc < 0) {
std::wcerr << L"加载文件失败" << std::endl;
return 1;
}
// 获取值
const wchar_t* value = ini.GetValue(L"section", L"key", L"默认值");
std::wcout << L"读取的值: " << value << std::endl;
return 0;
}
常见问题解决
-
中文乱码:
-
确保所有环节(源代码、配置文件、控制台输出)都使用 UTF-8
-
Windows 控制台可能需要
SetConsoleOutputCP(65001)
来正确显示 UTF-8
-
-
文件读写失败:
-
检查文件路径是否正确
-
确保有文件读写权限
-
-
跨平台兼容性:
-
在 Windows 上,可能需要处理 BOM 头
-
考虑使用
std::filesystem
处理路径,提高可移植性
-