C++开源库 – YAML-CPP – 使用教程
YAML 介绍
YAML是一种结构化的文档结构,类似于json,xml。相比于json,xml.yaml更适合做配置使用
yaml-cpp是常用的yaml库
YAML-CPP 环境安装
1. 下载源代码
git clone https://github.com/jbeder/yaml-cpp.git
2. 编译安装
mkdir build
cd build
cmake -DBUILD_SHARED_LIBS=ON ..
make install
使用教程
基础用法
测试用yaml文件:test.yml
logs:
- name: root
level: info
appenders:
- type: FileLogAppender
file: "./log.txt"
- type: StdoutLogAppender
- name: system
level: warn
appenders:
- type: FileLogAppender
file: "./log.txt"
- type: StdoutLogAppender
读取文件,输出文件
#include <yaml-cpp/yaml.h> //yaml-cpp 头文件
#include <iostream>
int main(int argc, char** argv) {
try {
YAML::Node node = YAML::LoadFile("file.yml");
std::cout << node << std::endl; //输出yaml数据
} catch (...) { //文件为非yaml格式抛出异常
std::cout << "error" << std::endl;
}
return 0;
}
按照自定义格式解析yaml
#include <iostream>
#include <yaml-cpp/yaml.h>
#include <vector>
struct Appender {
std::string type;
std::string file;
};
struct LogDefine {
std::string name;
std::string level;
std::vector<Appender> appenders;
};
int main(int argc, char** argv) {
try {
YAML::Node root = YAML::LoadFile("test.yml");
if(!root["logs"].IsDefined()) { //IsDefined() 判断节点是否存在
std::cout << "logs is null" << std::endl;
return 0;
}
if(!root["logs"].IsSequence()) {//因为logs是数组 IsSequence
std::cout << "logs is not sequence" << std::endl;
return 0;
}
std::vector<LogDefine> lds;
//sequence遍历方式 类似vector
for(size_t i = 0; i < root["logs"].size(); ++i) {
YAML::Node node = root["logs"][i];
if(!node.IsMap()) { //判断是否是map结构, IsMap
std::cout << node << " - not map" << std::endl;
continue;
}
LogDefine ld;
if(node["name"].IsDefined()) {
if(node["name"].IsScalar()) { //判断是否简单类型。IsScalar
ld.name = node["name"].IsScalar();
} else {
std::cout << "name not scalar" << std::endl;
}
}
if(node["level"].IsDefined()) {
if(node["level"].IsScalar()) { //判断是否简单类型。IsScalar
ld.name = node["level"].Scalar();
} else {
std::cout << "level not scalar" << std::endl;
}
}
if(node["appenders"].IsDefined()
&& node["appenders"].IsSequence()) {
Appender a;
for(size_t x = 0; x < node["appenders"].size(); ++x) {
YAML::Node xnode = node["appenders"][x];
if(xnode["type"].IsScalar()) {
xnode.type = xnode["type"].Scalar();
} else {
std::cout << "type not scalar" << std::endl;
}
if(xnode["file"].IsScalar()) {
xnode.type = xnode["file"].Scalar();
} else {
std::cout << "file not scalar" << std::endl;
}
ld.appenders.push_back(a);
}
}
lds.push_back(ld);
}
} catch (...) {
std::cout << "invalid yaml" << std::endl;
}
return 0;
}
将自定义格式转成YAML格式
按照自定义格式解析yaml
#include <iostream>
#include <yaml-cpp/yaml.h>
#include <vector>
struct Appender {
Appender(const std::string& _type, std::string& _file)
:type(_type)
,file(_file) {
}
std::string type;
std::string file;
};
struct LogDefine {
LogDefine(const std::string& _name, const std::string& _level)
:name(_name)
,_level(_level) {
}
std::string name;
std::string level;
std::vector<Appender> appenders;
};
int main(int argc, char** argv) {
std::vector<LogDefine> lds;
{
LogDefine ld("root", "info");
ld.appenders.push_back(Appender("FileLogAppender", "./root.txt"));
ld.appenders.push_back(Appender("StdoutLogAppender", ""));
lds.push_back(ld);
LogDefine ld2("system", "warn");
ld2.appenders.push_back(Appender("FileLogAppender", "./system.txt"));
lld2d.appenders.push_back(Appender("StdoutLogAppender", ""));
lds.push_back(ld2);
}
YAML::Node root;
for(auto& i : lds) {
YAML::Node node;
node["name"] = i.name;
node["level"] = i.level;
for(auto& a : i.appenders) {
YAML::Node anode;
anode["type"] = a.type;
if(!a.file.empty()) {
anode["file"] = a.file;
}
node["appenders"].push_back(anode);
}
root.push_back(node);
}
std::cout << root << std::endl;
return 0;
}
总结
基础用法如以上两个示例
读取之前需要判断节点是否定义,IsDefined
转换格式需要判断是否是对应的类型
Scalar()方法,对应string类型的节点类似于 as
其他基本类型,可以使用as