使用SimpleIni解析ini文件

本文详细介绍了一个跨平台的C++库SimpleIni,它支持Windows、WinCE和Linux系统,提供了简单的API用于操作ini配置文件。文章涵盖了SimpleIni的主要功能,如加载、保存、读取和修改INI文件的方法,以及如何使用该库进行实际操作的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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&param2=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;
}

注意事项

  1. 字符集设置

    • 使用 CSimpleIniA 并调用 SetUnicode(true) 来正确处理 UTF-8

    • 或者直接使用 CSimpleIniW 来处理宽字符

  2. 文件编码

    • 确保源文件保存为 UTF-8 编码(无 BOM)

    • 确保编辑器使用 UTF-8 编码保存配置文件

  3. 跨平台问题

    • 在 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;
}

常见问题解决

  1. 中文乱码

    • 确保所有环节(源代码、配置文件、控制台输出)都使用 UTF-8

    • Windows 控制台可能需要 SetConsoleOutputCP(65001) 来正确显示 UTF-8

  2. 文件读写失败

    • 检查文件路径是否正确

    • 确保有文件读写权限

  3. 跨平台兼容性

    • 在 Windows 上,可能需要处理 BOM 头

    • 考虑使用 std::filesystem 处理路径,提高可移植性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

byxdaz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值