c++常见配置文件格式 JSON、INI、XML、YAML 它们如何解析

1. INI 格式(最简单、Windows 原生)

示例 config.ini

ini

复制代码
[Server]
IP = 127.0.0.1
Port = 8080
MaxConn = 100

[App]
Name = MyServer
Version = 1.0.0

C++ 解析(Windows 原生 API,无需库)

cpp

运行

cpp 复制代码
windows:
-------------------------------------------
#include <Windows.h>

int main() {
    char ip[32] = {0};
    char port[16] = {0};

    // 读取
    GetPrivateProfileStringA("Server", "IP", "", ip, 32, "./config.ini");
    GetPrivateProfileStringA("Server", "Port", "", port, 16, "./config.ini");

    int portNum = atoi(port);
    return 0;
}

linux 
-------------------------------------------
/*   删除右边的空格   */
char *r_trim(char *szOutput, const char *szInput)
{
    char *p = NULL;
    assert(szInput != NULL);
    assert(szOutput != NULL);
    assert(szOutput != szInput);
    strcpy(szOutput, szInput);
    for(p = szOutput + strlen(szOutput) - 1; p >= szOutput && isspace(*p); --p)
    {
        ;
    }
    *(++p) = '\0';
    return szOutput;
}

/*   删除两边的空格   */
char * a_trim(char * szOutput, const char * szInput)
{
    char *p = NULL;
    assert(szInput != NULL);
    assert(szOutput != NULL);
    l_trim(szOutput, szInput);
    for   (p = szOutput + strlen(szOutput) - 1; p >= szOutput && isspace(*p); --p)
    {
        ;
    }
    *(++p) = '\0';
    return szOutput;
}
//获取配置文件项信息
int GetProfileString(const char *profile, const char *AppName, const char *KeyName, char *KeyVal, const char *oVal)
{
    char appname[32], keyname[32];

    char *buf, *c;
    char buf_i[KEYVALLEN], buf_o[KEYVALLEN];
    memcpy(KeyVal, oVal, strlen(oVal) + 1);
    FILE *fp;
    int found = 0; /* 1 AppName 2 KeyName */
    if ((fp = fopen(profile, "r")) == NULL)
    {
        if(g_iLogLevel & 1)
            printf("openfile [%s] error [%s]", profile, strerror(errno));
        return(-1);
    }
    fseek(fp, 0, SEEK_SET);
    memset(appname, 0, sizeof(appname));
    sprintf(appname, "[%s]", AppName);

    while (!feof(fp) && fgets(buf_i, KEYVALLEN, fp) != NULL)
    {
        l_trim(buf_o, buf_i);
        if (strlen(buf_o) <= 0)
            continue;
        buf = NULL;
        buf = buf_o;

        if (found == 0)
        {
            if (buf[0] != '[')
            {
                continue;
            }
            else if (strncmp(buf, appname, strlen(appname)) == 0)
            {
                found = 1;
                continue;
            }

        }
        else if (found == 1)
        {
            if (buf[0] == '#')
            {
                continue;
            }
            else if (buf[0] == '[')
            {
                break;
            }
            else
            {
                if ((c = (char*)strchr(buf, '=')) == NULL)
                    continue;
                memset(keyname, 0, sizeof(keyname));

                sscanf(buf, "%[^=|^ |^\t]", keyname);
                if (strcmp(keyname, KeyName) == 0)
                {
                    sscanf(++c, "%[^\n]", KeyVal);
                    char *KeyVal_o = (char *)malloc(strlen(KeyVal) + 1);
                    if (KeyVal_o != NULL)
                    {
                        memset(KeyVal_o, 0, strlen(KeyVal) + 1);
                        a_trim(KeyVal_o, KeyVal);
                        if (KeyVal_o && strlen(KeyVal_o) > 0)
                            strcpy(KeyVal, KeyVal_o);
                        free(KeyVal_o);
                        KeyVal_o = NULL;
                    }
                    found = 2;
                    break;
                }
                else
                {
                    continue;
                }
            }
        }
    }
    fclose(fp);
    if (found == 2)
        return(0);
    else
        return(-1);
}

优点

  • 最简单、开箱即用
  • Windows 原生 API,不需要任何第三方库
  • 轻量、人眼易读

缺点

  • 不支持嵌套、不支持数组
  • 仅适合简单配置

2. JSON(最通用、前后端通用)

示例 config.json

json

复制代码
{
    "Server": {
        "IP": "127.0.0.1",
        "Port": 8080,
        "MaxConn": 100
    },
    "App": {
        "Name": "MyServer",
        "Version": "1.0.0"
    }
}

C++ 解析(用 nlohmann/json,单头文件神器)

cpp

运行

复制代码
#include "nlohmann/json.hpp"
#include <fstream>
using json = nlohmann::json;

int main() {
    std::ifstream f("config.json");
    json data = json::parse(f);

    std::string ip = data["Server"]["IP"];
    int port = data["Server"]["Port"];
    std::string name = data["App"]["Name"];

    return 0;
}

优点

  • 几乎所有语言支持
  • 支持对象、数组、嵌套
  • 现代配置首选

缺点

  • 不能写注释(标准不支持)

3. XML(老式、偏重量级)

示例 config.xml

xml

复制代码
<Config>
    <Server>
        <IP>127.0.0.1</IP>
        <Port>8080</Port>
    </Server>
</Config>

C++ 解析(用 tinyxml2

cpp

运行

复制代码
#include "tinyxml2.h"
using namespace tinyxml2;

int main() {
    XMLDocument doc;
    doc.LoadFile("config.xml");

    XMLElement* server = doc.FirstChildElement("Config")->FirstChildElement("Server");
    const char* ip = server->FirstChildElement("IP")->GetText();

    return 0;
}

优点

  • 结构化强、可扩展
  • 企业 / 旧项目常用

缺点

  • 臃肿、标签冗余
  • 阅读麻烦、解析代码长

4. YAML(最优雅、可读性最高)

示例 config.yaml

yaml

复制代码
Server:
  IP: 127.0.0.1
  Port: 8080
  MaxConn: 100

App:
  Name: MyServer
  Version: 1.0.0

C++ 解析(用 yaml-cpp

cpp

运行

复制代码
#include <yaml-cpp/yaml.h>

int main() {
    YAML::Node config = YAML::LoadFile("config.yaml");

    std::string ip = config["Server"]["IP"].as<std::string>();
    int port = config["Server"]["Port"].as<int>();

    return 0;
}

优点

  • 人类友好,最干净
  • 支持注释、嵌套、数组
  • DevOps / 云原生 主流

缺点

  • 缩进敏感(像 Python)
  • C++ 库比 JSON 稍大

🚀 最终推荐

1. 最简单 → INI

2. 通用全能 → JSON(最推荐)

3. 优雅高级 → YAML

4. 老式企业项目 → XML

相关推荐
绝世唐门三哥2 分钟前
vue3中页面返回时刷新首页的处理方案
开发语言·前端·javascript
nianniannnn2 分钟前
c++复习自存--流、异常处理、多线程与C++工程规范
开发语言·c++
geovindu12 分钟前
CSharp: Dijkstra Algorithms
开发语言·后端·算法·c#
XR12345678818 分钟前
食品饮料与制药行业GMP合规网络建设:无尘车间的网络不能成为污染源
开发语言·网络·php
学逆向的36 分钟前
汇编——位运算
开发语言·汇编·算法·网络安全
zhangjw3444 分钟前
第29篇:Java伪共享与对象分配:并发性能优化的关键
java·开发语言·性能优化
公子小六1 小时前
基于.NET的Windows窗体编程之WinForms图像控件
windows·microsoft·c#·.net·winforms
知无不研1 小时前
缺省参数与缺省函数的区别
c++·语法
狂热开发者1 小时前
用 Typeoff 把会后口述整理成 Markdown 决策记录
人工智能·windows·macos·ios·安卓
Java面试题总结1 小时前
Python 开发技巧 · 高级装饰器 —— 从基础到工业级实战
开发语言·python