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

相关推荐
lclin_20201 天前
VS2010兼容|C++系统全能监控工具(彩色界面+日志带单位+完整版)
c++·windows·系统监控·vs2010·编程实战
以神为界1 天前
Python入门实操:基础语法+爬虫入门+模块使用全指南
开发语言·网络·爬虫·python·安全·web
逻辑驱动的ken1 天前
Java高频面试题:03
java·开发语言·面试·求职招聘·春招
噜噜大王_1 天前
深入理解 C 语言内存操作函数:memcpy、memmove、memset、memcmp
c语言·开发语言
神秘剑客_CN1 天前
windows自带FTP服务搭建及防火墙设置
windows
广师大-Wzx1 天前
一篇文章看懂MySQL数据库(下)
java·开发语言·数据结构·数据库·windows·python·mysql
野生技术架构师1 天前
Java NIO到底是个什么东西?
java·开发语言·nio
嵌入式×边缘AI:打怪升级日志1 天前
Qt GUI 程序开发完全学习笔记(从环境搭建到第一个界面程序
qt
lolo大魔王1 天前
Go语言的异常处理
开发语言·后端·golang
paeamecium1 天前
【PAT甲级真题】- Cars on Campus (30)
数据结构·c++·算法·pat考试·pat