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 稍大