当前位置:   article > 正文

C++操作YAML配置文件_c++ yaml

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这里有一点需要注意,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();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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

	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();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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

3 删 操作

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

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

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();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

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

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();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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

5 查 操作

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

5.1 数据类型

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

用代码验证一下上面:

	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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

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;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

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

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

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;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号