利用 yaml-cpp 开源库读写 yaml 配置文件—— 读写部分
YAML文件解析
Node
Node 是 yaml-cpp 中的核心概念,是最重要的数据结构,它用于存储解析后的 yaml 信息。
Node一共有以下几种type:
1)Null 空节点
2)Sequence 序列,类似于一个Vector,对应YAML格式中的数组
3)Map 类似标准库中的Map,对应YAML格式中的对象
4)Scalar 标量,对应YAML格式中的常量
生成 Node 的形式有很多种,loadFile() 是最常见的一种。
Node LoadFile(const std::string& filename) ,其中filename 就是yaml文件的路径。
有了 Node 之后,所有的信息都可以检索到。比如 name.
cout << “name:” << config[“name”].as() << endl;其中as()表示将解析的内容转换成 string 类型,也可以转换成其它类型。
读写yaml文件
假设配置文件config.yaml
config.yaml内容
name: frank
sex: male
age: 18
skills:
c++: 1
java: 1
android: 1
python: 1
注意:yaml 中的内容,: 后面一定要加空格
test_yaml.cpp文件内容
#include <iostream>
#include "yaml-cpp/yaml.h"
#include <fstream>
using namespace std;
int main(int argc,char** argv)
{
YAML::Node config;
try{
config = YAML::LoadFile("../config.yaml");
} catch(YAML::BadFile &e) {
std::cout<<"read error"<<std::endl;
return -1;
}
cout << "Node type " << config.Type() << endl;
cout << "skills type " << config["skills"].Type() << endl;
cout << "name:" << config["name"].as<string>() << endl;
cout << "sex:" << config["sex"].as<string>() << endl;
cout << "age:" << config["age"].as<int>() << endl;
//读取不存在的node值,报YAML::TypedBadConversion异常
try{
string label = config["label"].as<string>();
}catch(YAML::TypedBadConversion<string> &e){
std::cout<<"label node is NULL"<<std::endl;
}//TypedBadConversion是模板类,读取什么类型的参数就传入什么类型
cout << "skills c++:" << config["skills"]["c++"].as<int>() << endl;
cout << "skills java:" << config["skills"]["java"].as<int>() << endl;
cout << "skills android:" << config["skills"]["android"].as<int>() << endl;
cout << "skills python:" << config["skills"]["python"].as<int>() << endl;
//通过迭代的方式,访问 skills 下面的各个元素
for(YAML::const_iterator it= config["skills"].begin(); it != config["skills"].end();++it)
{
cout << it->first.as<string>() << ":" << it->second.as<int>() << endl;
}
YAML::Node test1 = YAML::Load("[1,2,3,4]");
cout << " Type: " << test1.Type() << endl;
YAML::Node test2 = YAML::Load("1");
cout << " Type: " << test2.Type() << endl;
YAML::Node test3 = YAML::Load("{'id':1,'degree':'senior'}");
cout << " Type: " << test3.Type() << endl;
//将score 写入./testconfig.yaml
ofstream fout("./testconfig.yaml");
config["score"] = 99;//添加新元素
fout << config;
fout.close();
return 0;
}
重要内容简单解释
1)Node
Node 是 yaml-cpp 中的核心概念,它用于存储解析后的 yaml 信息。
生成 Node 的形式有很多种, loadFile() 是最常见的一种。
Node LoadFile(const std::string& filename)
filename 就是配置文件的路径。
有了 Node 之后,所有的信息都可以检索到。
2)skills 的信息怎么读呢?
skills:
c++: 1
java: 1
android: 1
python: 1
其实也非常简单
cout << "skills c++:" << config["skills"]["c++"].as<int>() << endl;
cout << "skills java:" << config["skills"]["java"].as<int>() << endl;
cout << "skills android:" << config["skills"]["android"].as<int>() << endl;
cout << "skills python:" << config["skills"]["python"].as<int>() << endl;
yaml-cpp 中也可以通过迭代的方式,访问 Node 中的内容
比如,访问 skills 下面的各个元素
for(YAML::const_iterator it= config["skills"].begin(); it != config["skills"].end();++it)
{
cout << it->first.as<string>() << ":" << it->second.as<int>() << endl;
}
用 begin() 获取迭代器,用 end() 判断迭代器是否结束。
3)NodeType
yaml 支持 Scalar、List、Map 类型,yaml-cpp 通过 NodeType 定义了 Node 的可能类型。
namespace YAML {
struct NodeType {
enum value { Undefined, Null, Scalar, Sequence, Map };
};
}
对应未定义、空、标量、序列、字典。
YAML::Node test1 = YAML::Load("[1,2,3,4]");
cout << " Type: " << test1.Type() << endl;
YAML::Node test2 = YAML::Load("1");
cout << " Type: " << test2.Type() << endl;
YAML::Node test3 = YAML::Load("{'id':1,'degree':'senior'}");
cout << " Type: " << test3.Type() << endl;
上面的代码是为了判断 NodeType。
结果如下:
Type: 3
Type: 2
Type: 4
分别对应 Sequence、Scalar、Map。
4)yaml-cpp 写配置文件
日常开发中,除了读取配置参数,我们经常需要保存参数,yaml-cpp也提供了相应的功能。
ofstream fout("./testconfig.yaml");
config["score"] = 99;
fout << config;
fout.close();
将读取的config,添加一个 score,然后保存。
运行代码后,发现 build 文件夹下多了 testconfig.xml 文件,score 也被添加进去。
name: frank
sex: male
age: 18
skills:
c++: 1
java: 1
android: 1
python: 1
score: 99
5)总结:
std::ifstream file(“config.yaml”);
YAML::Node node = YAML::Load(file);//读取来自test.yaml的node文件YAML
std::cout << node <<std::endl;
//或者
YAML::Node node_2 = YAML::LoadFile(“config.yaml”);//也可以这样读取文件
std::cout << node_2[“node_2”] <<std::endl;//可以直接用下标访问
for(auto it = node_2.begin(); it != node_2.end(); it++)
std::cout << it->first << it->second << std::endl;//也可以用迭代器访问
node的增改查删
#include <fstream>
#include <yaml-cpp/yaml.h>
#include <iostream>
#include <assert.h>
int main()
{
YAML::Node node;
assert(node.IsNull()); //初始化的节点是Null类型
node["key"] = "value";
//node.force_insert("key", "value");//这个操作和上面等价,但是它不会检查是否存在"key"键,不推荐使用
if(node["mascot"])
std::cout << node["mascot"].as<std::string>() << "\n";//单纯的查询操作不会增加一个key,当然上面的if不会执行
node["number"] = 255;
assert(node.IsMap()); //node是一个Map
node["seq"].push_back("first element");
node["seq"].push_back("second element");//node的seq下是Sequence类型,有两个参数
YAML::Node node_2;
node_2.push_back("first_item");//如果不给node_2键值对,它是一个sequence类型
node_2.push_back("second_item");
node_2.push_back("third_item");
std::vector<int> v = {1,3,5,7,9};//给node_2插入了一个Sequence
node_2.push_back(v);
assert(node_2.IsSequence());//node_2仍然是一个Sequence
assert(node_2[0].as<std::string>() == "first item");
//对于Sequence类型,你可以使用它的下标来访问
//注意这里as<T>是一个模板转换,node_2[0]的type是NodeType::Scalar
auto it = node_2.begin();
for(; it != node_2.end(); it++)
std::cout << *(it) << std::endl;
//当然,可以用迭代器来访问
//它们的类型分别是NodeType::Scalar,NodeType::Scalar,NodeType::Scalar,NodeType::Sequence
//取值时记得使用as进行模板转换
node_2["key"] = "value";
assert(node_2.IsMap());//一旦node_2接收到键值对,它转变为Map类型
assert(node_2[0].as<std::string>() == "first item");//此时,Sequence时的下标变为它的key值
node["node_2"] = node_2;//将node_2作为node的一个子项
node["pointer_to_first_element"] = node["seq"][0];//也可以给已有的node设置一个别名,类似于一个指针
assert(node["pointer_to_first_element"].as<std::string>() == "first element");//可以通过这个指针访问那个node
//node.remove(node["seq"][0]);//可以通过指定一个node来删除它
//node.remove("pointer_to_first_element");//也可以通过指定key来删除它
std::cout << node << endl;
}
最后cout的结果如下:
key: value
number: 255
seq:
- first element
- second element
node_2:
0: first item
1: second_item
2: third_item
3:
- 1
- 3
- 5
- 7
- 9
key: value
注:如有侵权,请联系删除!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/130094.html