这篇文章主要介绍“c++怎么读写yaml配置文件”,在日常操作中,相信很多人在c++怎么读写yaml配置文件问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”c++怎么读写yaml配置文件”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
YAML基础语法
YAML所表示的YAML Ain’t MarkuP Language,YAML 是一种简洁的非标记语言。YAML以数据为中心,使用空白,缩进,分行组织数据,从而使得表示更加简洁易读。
基本规则
YAML有以下基本规则:
1、大小写敏感
2、使用缩进表示层级关系
3、禁止使用tab缩进,只能使用空格键
4、缩进长度没有限制,只要元素对齐就表示这些元素属于一个层级。
5、使用#表示注释
6、字符串可以不用引号标注
三种数据结构
map,散列表
使用冒号(:)表示键值对,同一缩进的所有键值对属于一个map,示例:
# YAML表示 age : 12 name : huang # 对应的Json表示 {'age':12,'name':'huang'}
list,数组
使用连字符(-)表示:
# YAML表示 - a - b - 12 # 对应Json表示 ['a','b',12]
也可以写在一行:
# YAML表示 [a,b,c] # 对应Json表示 [ 'a', 'b', 'c' ]
scalar,纯量
数据最小的单位,不可以再分割。
数据结构嵌套
map和list的元素可以是另一个map或者list或者是纯量。由此出现4种常见的数据嵌套:
map嵌套map
# YAML表示 websites: YAML: yaml.org Ruby: ruby-lang.org Python: python.org Perl: use.perl.org # 对应Json表示 { websites: { YAML: 'yaml.org', Ruby: 'ruby-lang.org', Python: 'python.org', Perl: 'use.perl.org' } }
map嵌套list
# YAML表示 languages: - Ruby - Perl - Python - c # 对应Json表示 { languages: [ 'Ruby', 'Perl', 'Python', 'c' ] }
list嵌套list
# YAML表示 - - Ruby - Perl - Python - - c - c++ - java # 对应Json表示 [ [ 'Ruby', 'Perl', 'Python' ], [ 'c', 'c++', 'java' ] ]
除此以外,还可以如下表示该结构
# 方法2 - - Ruby - Perl - Python - - c - c++ - java # 方法3 - [Ruby,Perl,Python] - [c,c++,java]
list嵌套map
# YAML表示 - id: 1 name: huang - id: 2 name: liao # 对应Json表示 [ { id: 1, name: 'huang' }, { id: 2, name: 'liao' } ]
利用yaml-cpp读写yaml配置文件
yaml-cpp 是一个开源库
yaml-cpp 是通过 CMake 来进行构建和编译的。
首先下载源码
mkdir build
cd build cmake ..
注意的是 cmake 后面是 …,这代表从 build 上一层目录查找 CMakeLists.txt ,然后编译的文件都会存放在 build 文件夹,如果对编译的效果不满意,只要删除 build 文件就好了,其他源码目录并不受影响,这是 cmake 编译时的基本套路。
yaml-cpp 默认构建的就是静态库,也就是 unix 类系统下的 .a 文件,如果你想构建动态库的话,就需要在 cmake 时指定。
cmake .. -D BUILD_SHARED_LIBS=ON
编译成功后,会生成库文件,你只需要将库文件和头文件拷贝到你自己的工程当中,就可以使用了。
需要处理好头文件。
你如果不想每次都到 copy 头文件到不同的工程中,那么你可以将头文件 copy 到系统默认的头文件目录,比如 ubuntu 的地址是 /usr/local/include,
将库文件拷贝到系统默认的 lib 文件就好了,比如 ubuntu 是 /usr/local/lib。
读取 yaml 配置文件
name: frank sex: male age: 18 skills: c++: 1 java: 1 android: 1 python: 1
温馨提示:yaml 中的内容,:后面一定要加空格哦
现在,我们的目标是要把它正确的读取出来。
yaml_test.cpp
#include <iostream> #include "include/yaml-cpp/yaml.h" using namespace std; int main(int argc,char** argv) { YAML::Node config = YAML::LoadFile("../config.yaml"); cout << "name:" << config["name"].as<string>() << endl; cout << "sex:" << config["sex"].as<string>() << endl; cout << "age:" << config["age"].as<int>() << endl; return 0; }
头文件在/usr/local/include目录下
库文件在/usr/local/lib目录下
然后通过 cmake 编译,因为我习惯用 cmake,如果读者喜欢用原始的 g++ 编译或者 makefile 也是可以的。
我的 CMakeFileLists.txt 如下:
cmake_minimum_required(VERSION 3.2) project(yaml_test) add_deFinitions(-std=c++11) #set(CMAKE_CXX_STANDARD 11) include_directories(/usr/local/include/yaml-cpp)#头文件路径 set(SRCS src/yaml_test.cpp) add_executable(yamltest ${SRCS}) target_link_libraries(yamltest /usr/local/lib/libyaml-cpp.so)#库文件路径
在当前目录创建 build 文件夹,然后进入 build 文件执行 cmake 操作。
mkdir buildcd buildcmake ..
执行后,输出的信息如下。
name:frank sex:male age:18
Node
Node 是 yaml-cpp 中的核心概念,它用于存储解析后的 yaml 信息。
生成 Node 的形式有很多种, loadFile() 是最常见的一种。
Node LoadFile(const std::string& filename)
filename 就是配置文件的路径。
有了 Node 之后,所有的信息都可以检索到。
比如 name.
cout << "name:" << config["name"].as<string>() << endl;
as()表示将解析的内容转换成 string 类型。
你也可以转换成其它类型。
有同学可能会有疑惑。
skills: c++: 1 java: 1 android: 1 python: 1
skills 的信息怎么读呢?
其实也非常简单。
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 中的迭代
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() 判断迭代器是否结束。
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。
yaml-cpp 写配置文件
日常开发中,除了读取配置参数,我们经常需要保存参数,yaml-cpp 自然也提供了相应的功能。
ofstream fout("testconfig.xml"); 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
到此,yaml-cpp 的简单使用就 OK 了,读者可以查看代码去深入学习。
完整代码:
yaml_test.cpp
#include <iostream> #include <fstream> #include <yaml-cpp/yaml.h> using namespace std; int main(int argc,char ** argv) { YAML::Node config = YAML::LoadFile("../config/config.yaml"); cout<<"Nod 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; 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; 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; ofstream fout("../config/testconfig.yaml"); config["score"] = 99; fout << config; fout.close(); return 0; }
到此,关于“c++怎么读写yaml配置文件”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程之家网站,小编会继续努力为大家带来更多实用的文章!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。