yaml-cpp
引言
基本信息:
yaml
:YAML是专门用来写配置文件的语言,非常简洁和强大,比json和xml格式要方便很多,更容易阅读yaml-cpp
:是一个开源的C++解析yaml配置文件的库,我们可以使用该库进行解析项目中的yaml文件
windows添加环境变量:
-
右键点击此电脑,点击属性,选择高级系统设置(或者打开设置,进入系统选型卡,点击系统信息,然后点击高级系统设置),点击环境变量后
-
在用户变量中的双击Path,然后新建,将需要添加到环境变量中的地址放入,然后确定
安装准备:
-
下载源码包
git clone git@github.com:jbeder/yaml-cpp.git
-
进入yaml-cpp目录后,创建build目录并且进入
# linux cd yaml-cpp mkdir build && cd build # windows cd yaml-cpp mkdir build cd build
-
将其编译成动态库或静态库来链接到项目中使用
-
安装cmake和编译工具
windows
:进入Download CMake进行下载安装适合的cmke环境,点击w64devkit安装编译环境工具,然后将安装cmake和w64devkit的bin目录地址添加到环境变量中Linux
:使用命令行安装Moon’s CMake
注意:这里windows编译库的方法是用mingw的编译工具的,如果需要VS或者Ninja就去百度来查找进行编译
Windows编译库:
-
进入到yaml-cpp目录下的build目录后用终端打开(右键文件夹)
-
执行以下命令:
cmake .. -G “MinGW Makefiles” # 需要生成动态库执行以下命令 cmake .. -G “MinGW Makefiles” -D BUILD_SHARED_LIBS=ON # 进行make生成 make # 如果需要安装可以 make install
Linux编译库:
cd yaml-cpp
mkdir build && cd build
cmake .. && make
# 需要动态库
cmake .. -D BUILD_SHARED_LIBS=ON && make
# 需要安装
sudo make install
YAML语法
基本语法:
- 大小写敏感
- 使用缩进表示层级关系
- 缩进不允许使用tab,只允许空格
- 缩进的空格数不重要,只要相同层级的元素左对齐即可
'#'表示注释
字符串默认不使用引号表示
,如果字符串之中包含空格或特殊字符,需要放在引号之中- 单引号和双引号都可以使用,双引号不会对特殊字符转义
- 单引号之中如果还有单引号,必须连续使用两个单引号转义
- 字符串可以写成多行,从第二行开始,必须有一个单空格缩进,换行符会被转为空格
映射写法为 key: value
,冒号后需要带空格
标量(Scalars)
:单个的、不可再分的值(date、boolean、string、number、null、字符串、浮点数、时间、日期)
# 写法
k: v
对象(Map)
:键值对的集合(map、hash、set、object),又称为映射/哈希/字典
# 行内写法
k: {k1:v1,k2:v2,k3:v3}
# 或分层写法
k:
k1: v1
k2: v2
k3: v3
数组(Sequence)
:一组按次序排列的值(array、list、queue)
# 行内写法
k: [v1,v2,v3]
# 或分层写法
k:
- v1
- v2
- v3
引用
:
-
可以通过引用另一个变量来设置value,使用${}引用变量
# 定义变量 test: p: 1 test1: 1 name: p1: ${test.p} p2: ${test1}
-
通过引用
锚点&
来设置值,用*来取锚点值
,可以通过<<:
将键值对一起引入# 设置锚点 test: &test-c p: 1 name: <<: *test-c
-
通过使用
锚点&
来设置键,用*来取锚点值
test: p1: &test-p1 pp1 p2: &test-p2 pp2 name: *test-p1: 1 *test-p2: 2
yaml-cpp使用
引入头文件:
#include "yaml-cpp/yaml.h"
Node
- 概念:Node 是 yaml-cpp 中的核心概念,是最重要的数据结构,它用于存储解析后的yaml信息
type
:未定义(Undefined)、空节点(Null)、标量(Scalar)、数组(Sequence)、对象(Map)
namespace YAML {
struct NodeType {
enum value { Undefined, Null, Scalar, Sequence, Map };
};
}
//定义节点
YAML::Node node; //初始化为null类型
检查节点类型
:
//示例:
if (config["key"].IsScalar()) {
// 处理标量
} else if (config["key"].IsSequence()) {
// 处理序列
} else if (config["key"].IsMap()) {
// 处理映射
}
赋值
:
//定义节点
YAML::Node node;
//标量赋值
node["key"]="value";
//对象赋值
YAML::Node node1;
node1["key"]["p1"]=1;
node1["key"]["p2"]=2;
//对象中插入值
node1["seq"].push_back("1");
//数组赋值
YAML::Node node2;
node2.push_back("1");
node2.push_back("2");
//数组转变map
node2["key"]="value";
//插入数组
YAML::Node node3;
std::vector<int> v = {1,2,3,4};
node3.push_back(v);
//将node2和node3作为node的子项
node["node2"]=node2;
node["node3"]=node3;
//输出查看
std::cout<<node<<std::endl;
取值
:使用.as()来将值以type类型取出
//取值模板
type value=<Node name>["key"].as<type>();
type value=<Node name>["key"]["key1"].as<type>();
//示例:
//标量取值
std::string ip=config["ip"].as<std::string>();
//对象取值
int port=config["settings"]["port"].as<int>();
删除
:使用remove方法进行删除指定节点中的键和指定键
node.remove("key"); //通过指定键删除
node.remove(node["seq"]["0"]); //删除指定节点中的键
迭代
:使用YAML::const_iterator迭代器
-
解析数组:
//YAML的迭代器为YAML::const_iterator for(YAML::const_iterator it=config["key"].begin();it!=config["items"].end();++it){ std::cout<<it->as<type>()<<std::endl; } //或者 for(auto it=config["key"].begin();it!=config["items"].end();++it){ std::cout<<it->as<type>()<<std::endl; } //或者 for(auto const &it:config["items"]){ std::cout<<it.as<std::string>()<<std::endl; }
-
解析对象:
//YAML的迭代器为YAML::const_iterator for(YAML::const_iterator it=config["key"].begin();it!=config["items"].end();++it){ std::string key = it->first.as<std::string>(); std::string value = it->second.as<std::string>(); std::cout << key << ": " << value << std::endl; } //或者 for(auto it=config["key"].begin();it!=config["items"].end();++it){ std::string key = it->first.as<std::string>(); std::string value = it->second.as<std::string>(); std::cout << key << ": " << value << std::endl; } //或者 for(auto const &it:config["items"]){ std::string key = it.first.as<std::string>(); std::string value = it.second.as<std::string>(); std::cout << key << ": " << value << std::endl; }
读取yaml文件
:使用Load或者LoadFile方法
std::ifstream file("config.yml");
YAML::Node node = YAML::Load(file);//读取来自config.yml的node文件
std::cout << node <<std::endl;
//或者
YAML::Node node_2 = YAML::LoadFile("config.yml");//也可以这样读取文件
保存yaml文件/输出
:
YAML::Node out;
std::ofstream fout("output.yaml");
//更改out里的数据
...
fout << out;
fout.close();