C++操作YAML配置文件

1 下载安装YAML开源库

方法1:

YAML是一个开源库,源代码可以在GitHub下载到,链接:

https://github.com/jbeder/yaml-cpp

yaml-cpp 是通过 CMake 来进行构建和编译的。使用CMake的方法可以自行百度,网上

一大堆。

方法2:

直接百度网盘下载我这里构建好的,包含64位和32位两个版本。
附上链接:
链接:https://pan.baidu.com/s/1_QYPX2IpP7UWlEteRJCeqw
提取码:ehmp
在这里插入图片描述
嫌麻烦的或者没有CMake操作经验的,可以直接百度网盘下载对应文件。

2 使用visual studio 2017 链接YAML

1 新建工程

首先根据自己需要下载一个32位或者64位的控制台程序。将下载好或者自行编译好的文件夹放到自己的工程目录下面。为了操作方便,我这里直接放到了了和 .sln 同一级的目录下。
在这里插入图片描述

2 更改工程项目属性

用vs打开工程之后,点击上方工具栏中的项目,找到最下方的项目属性。分别在属性页中的C/C++:常规。链接器:常规和输入完成相关配置。配置结果如下。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3 进行文件包含

使用过C/C++编程的人都知道,在使用某个库之前,我们需要包含它的头文件,然后才能使用里面的函数。在上面链接好工程之后,在main.cpp里面包含YAML库的头文件,如果能包含成功,则说明配置无误,若包含失败,请检查上面操作步骤。
在这里插入图片描述

3 使用YAML进行 “增删改查” 的基本操作

完成操作之后,我们开始文件的基本操作 “增删改查”。
一般来说,我们用C/C++进行文件操作时,需要不断偏移文件的指针去解析自己想要的内容。在YAML操作这里,首先让我们先忘掉指针操作。

1 为方便操作,新建一个配置文件

name: dong
number: 1
age:
  skills:
    eat: 2
    drink: 3
    play: 4
    study: 5
self: 99

这里有一点需要注意,YAML是一个严格按照空格进行区分节和子节的一种格式语言。若不在同一缩进的格式下,计时在同一个节下面,也会将其分为不同子节。下面验证一下。

2 增 操作

YAML文件的增加操作,目前我喜欢用两种方法,分别为 push_back方法和数组操作方法,下面用一段代码分别介绍。

	YAML::Node config;	//< 创建节点
	config.IsNull();	//< 初始化节点
	ofstream fout("../dong1.yaml"); //< C++ stream 读取文件

	config["123"] = 456;	//< 插入格式 1  直接插入第一节
	config["456"].push_back(789); //< 插入格式2  插入第一节

	fout << config;

	fout.close();

这里可以看一下两者放入方法的不同区别:贴图如下:
在这里插入图片描述
可以看到,用第一种方法插入的直接对键进行了赋值,第二种方法,则是在键下面新建了一个 “标量”。可以根据需要来决定采取何种插入方法。这里可能会有人有疑问:如果我想要在某一个子节下面增加数据,该如何操作。下面贴上代码:

	YAML::Node config;	//< 创建节点
	config.IsNull();	//< 初始化节点
	ofstream fout("../dong1.yaml"); //< C++ stream 读取文件

	config["123"]["456"] = 456;	//< 插入格式 1  直接插入第一节
	config["456"].push_back(789); //< 插入格式2  插入第一节

	fout << config;

	fout.close();

在这里插入图片描述
只需要在后面新加一个中括号即可解决问题。

3 删 操作

YAML文件的删除需要用到 remove函数。该函数有两种用法,下面用一个例子来分别介绍。
源数据:

name: dong
number: 1
skills:
    eat: 2
    drink: 3
    play: 4
    study: 5
self: 99

remove的用法:

	//< 删
	YAML::Node config = YAML::LoadFile("../dong.yaml");
	config["skills"].remove("eat");//< 1、删除skills下面的eat元素
	config.remove("number");//< 2、通过指定key来删除
	ofstream fout("../dong2.yaml"); //< C++ stream 读写文件
	fout << config;

	fout.close();

运行完之后的结果如下图:
在这里插入图片描述

可以看到已经将所指出的饿两个文件删除掉了

4 改 操作

改操作和上面的增操作类似,增操作是新增一个不存在的键或者节。改的操作只需要将其修改为已经存在的值,具体实现如下:

	//< 改
	YAML::Node config = YAML::LoadFile("../dong.yaml");
	ofstream fout("../dong1.yaml"); //< C++ stream 读取文件

	config["skills"]["eat"] = 10;	//< 修改格式 1
	config["name"] = "hening"; //< 修改格式2

	fout << config;

	fout.close();

可以看到,上面分别修改了两个点的内容,修改结果如下所示:
在这里插入图片描述
可以看到,修改操作和插入操作基本相同。

5 查 操作

查询操作基本上是我们用到的最多的操作了,了解到了以上三种 增、删、改的操作,下面的查询操作基本上就是小菜一碟了,下面首先介绍一下yaml的几种数据类型。

5.1 数据类型

//分别为:未定义、空、标量、序列、字典。
enum value { Undefined, Null, Scalar, Sequence, Map };

用代码验证一下上面:

	YAML::Node test1 = YAML::Load("[1,2,3,4]");
	cout << " Type: " << test1.Type() << endl;  //< 3

	YAML::Node test2 = YAML::Load("1");
	cout << " Type: " << test2.Type() << endl; //< 2

	YAML::Node test3 = YAML::Load("{'first':'dong' 'last':'hening'}");
	cout << " Type: " << test3.Type() << endl; //< 4

分别对应位 序列、标量以及字典:
在这里插入图片描述

5.2 查询数据

依旧是读取dong.yaml文件的内容。
基本查询,首先查询节的内容,不包括子节。

在这里插入代码片	YAML::Node config = YAML::LoadFile("../dong.yaml");
	for (auto it : config) {
		cout << it.first.as<string>() << endl; //< 指定数据类型
	}
	//< 这里使用 auto 可能不好理解,下面给出基本迭代器的使用
	for (YAML::const_iterator it = config.begin(); it != config.end(); it++){
		cout << it->first.as<string>() << endl;
	}

这里使用迭代器的方法进行查询,查询到的结果需要为其指定数据类型后输出。
运行结果如下:
在这里插入图片描述
如果我们想要查询子键的内容该如何去操作,基本上和上面的操作相同,只需要在中括号内为其指定即可:

	YAML::Node config = YAML::LoadFile("../dong.yaml");
	for (auto it : config["skills"]) {
		cout << it.first.as<string>() << ":" << it.second.as<string>() << endl;
	}

运行结果:
在这里插入图片描述

5.3 空值处理

这里有一点需要注意,我这里采用了second来读取了该键所对应的值,若此键没有设置值该怎么办?
下面我把eat所对应的2删除掉,运行一遍,给出结果:
在这里插入图片描述
他为我们自动填充了null类型,此时我们若要采用此值就需要判断其数据类型。

	YAML::Node config = YAML::LoadFile("../dong.yaml");
	for (auto it : config["skills"]) {
		YAML::Node test2 = YAML::Load(it.second.as<string>());
		cout << " Type: " << test2.Type() << endl; //< 2
		cout << it.first.as<string>() << ":" << it.second.as<string>() << endl;
	}

在这里插入图片描述
可以看到运行结果,判断类型为空。可以根据判断的类型做特殊处理。

5.4 常见错误

这里我们修改文件如下:
在这里插入图片描述
可以看到,我们给skills设置了值,这里看一下运行结果:
在这里插入图片描述
直接报出异常!结论显而易见。不能再一个键值对下面设置子键。对于节和键要区分开来。

结论

贴上完整代码:

#include <iostream>
#include "yaml-cpp/yaml.h"
#include <string>
#include <fstream>

using namespace std;

//分别为:未定义、空、标量、序列、字典。
//enum value { Undefined, Null, Scalar, Sequence, Map };


int main(){

	//< 增

	//YAML::Node config;	//< 创建节点
	//config.IsNull();	//< 初始化节点
	//ofstream fout("../dong1.yaml"); //< C++ stream 读取文件

	//config["123"]["456"] = 456;	//< 插入格式 1  直接插入第一节
	//config["456"].push_back(789); //< 插入格式2  插入第一节

	//fout << config;

	//fout.close();


	//< 删
	//YAML::Node config = YAML::LoadFile("../dong.yaml");
	//config["skills"].remove("eat");//你可以通过指定一个node来删除它
	//config.remove("number");//你也可以通过指定key来删除它

	//ofstream fout("../dong2.yaml"); //< C++ stream 读取文件
	//fout << config;

	//fout.close();


	////< 改
	//YAML::Node config = YAML::LoadFile("../dong.yaml");
	//ofstream fout("../dong1.yaml"); //< C++ stream 读取文件

	//config["skills"]["eat"] = 10;	//< 修改格式1 
	//config["name"] = "hening"; //< 修改格式2 

	//fout << config;

	//fout.close();


	////< 查
	//////////////////////////////////////////////////////////////////////////
///< Type Judge link to row 112 to 113

	//YAML::Node test1 = YAML::Load("[1,2,3,4]");
	//cout << " Type: " << test1.Type() << endl;  //< 3

	//YAML::Node test2 = YAML::Load("1");
	//cout << " Type: " << test2.Type() << endl; //< 2

	//YAML::Node test3 = YAML::Load("{'id':1 'degree':'senior'}");
	//cout << " Type: " << test3.Type() << endl; //< 4


	YAML::Node config = YAML::LoadFile("../dong.yaml");
	for (auto it : config["skills"]) {
		YAML::Node test2 = YAML::Load(it.second.as<string>());
		cout << " Type: " << test2.Type() << endl; //< 2
		cout << it.first.as<string>() << ":" << it.second.as<string>() << endl;
	}

	for (YAML::const_iterator it = config.begin(); it != config.end(); it++)
	{
		cout << it->first.as<string>() << endl;
	}
	system("pause");
    return 0;
}
### 创建 YAML 配置文件的指南 YAML 是一种轻量级的人类可读数据序列化格式,适用于配置文件、日志记录以及许多其他用途。以下是创建 YAML 配置文件的详细指南和示例。 #### 1. 基础概念 YAML 使用缩进表示层级结构,不允许使用制表符(Tab),只接受空格作为缩进字符[^2]。每一层通常采用两个空格进行缩进。 #### 2. 字面量与键值对 最基本的 YAML 结构是由键值对组成,形式为 `key: value`。例如: ```yaml name: John Doe age: 30 email: john.doe@example.com ``` #### 3. 列表 列表可以通过 `-` 符号来定义,适合存储一组有序或无序的数据项。例如: ```yaml hobbies: - Reading - Traveling - Coding ``` #### 4. 映射与嵌套 映射可以包含更复杂的嵌套结构,用于描述多层次的对象关系。例如: ```yaml user: name: Jane Smith age: 25 address: street: 123 Main St city: Springfield zip: 62704 ``` #### 5. 多文档支持 YAML 支持在一个文件中定义多个独立的文档,通过 `---` 分隔符实现。例如: ```yaml --- name: Document One content: This is the first document. --- name: Document Two content: This is the second document. ``` #### 6. 注释 可以在 YAML 文件中添加注释以解释特定字段的作用。注释以 `#` 开始,后续内容会被忽略。例如: ```yaml # 用户基本信息 username: admin password: secret # 密码应加密保存 ``` #### 7. 实际应用场景 以下是一个 Kubernetes Deployment 的 YAML 配置文件示例[^3],展示了如何定义一个运行 Nginx 容器的应用程序部署: ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80 ``` #### 8. 在不同编程语言中的解析 不同的编程语言提供了相应的库来处理 YAML 文件。例如,在 C++ 中可以使用 `yaml-cpp` 库[^1];而在 Go 语言中,则有专门的支持包可用于解析和生成 YAML 数据。 --- ###
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值