YAML文件作为常用的序列化语言,通常用于数据的保存上。那么我们在c++中如何使用YAML语言呢?这篇博客将集中与c++项目在visual studio上yaml-cpp的安装以及使用YAML语言对数据进行增删查改上。
1、yaml-cpp在visual studio上的安装
我个人用的版本是visual studio 2022,首先在github上获取yaml-cpp项目,链接为
下载后使用cmake对yaml-cpp项目进行编译
编译器和平台自己电脑上配置的版本,否则会报错。编译结果如下,提示编译成功。
然后我们在使用yaml-cpp时需要对文件路径进行配置
首先,对yaml头文件进行包含,选中yaml文件所在目录
然后,对项目所需要的静态库文件(使用cmake生成)进行链接。在链接器常规子目录下找到附加库目录,设置为静态库文件所在的目录。
在链接器输入子目录下找到附加依赖项,输入所需要的静态库文件
最后对动态库进行链接,将动态库文件yaml_cppd.dll文件移动至exe文件下
动态库链接的具体方式可参考:
最后可实现对yaml文件的操作,测试代码如下:
#include "yaml-cpp/yaml.h"
#include <fstream>
int main()
{
YAML::Node config;
std::ofstream fout("file1.yml"); //< C++ stream 读取文件
config["skills"]["eat"] = 10; //< 修改格式1
config["name"] = "hening"; //< 修改格式2
fout << config;
fout.close();
return 0;
}
2、yaml数据的增删改查实现
yaml数据的数据格式主要分为三种:mapping(对象)、sequence(数组)、scalars(标量)
yaml数据结构参考博客:[C++]-yml库yaml-cpp简介_alwaysrun的博客-CSDN博客_yaml-cpp
yaml数据的增加:
void Add(std::string fileName, YAML::Node config)
{
std::ofstream fout(fileName, std::ios::app);
fout << std::endl << config;
fout.close();
}
yaml数据的修改:
void Change(std::string fileName, YAML::Node config)
{
std::ofstream fout(fileName);
fout << std::endl << config;
fout.close();
}
yaml数据的查询:
初始Node节点默认为map类型,当yaml读取数据时,根据节点的不同进行递归查询。本查询默认结果输出为字符串类型。
void Query(YAML::Node config)
{
//enum value { Undefined, Null, Scalar, Sequence, Map };
switch (config.Type() )
{
case 0:
case 1:
break;
case 2: //scalar
{
std::cout << config.as<std::string>() << std::endl;
break;
}
case 3: //sequence
{
std::cout << std::endl;
for (auto it_1 : config)
{
std::cout << std::setw(3)<<"-";
Query(it_1);
}
break;
}
case 4: //map
{
std::cout << std::endl;
for (auto it_1 : config)
{
std::cout << std::setw(5) << it_1.first.as<std::string>() << ":";
YAML::Node NodeNext = it_1.second;
Query(NodeNext);
}
break;
}
default:
break;
}
}
yaml节点的删除:直接使用remove指令即可
config["skills"].remove("eat");
附上文件全部代码
#include "yaml-cpp/yaml.h"
#include <fstream>
#include <string>
#include <iostream>
#include <iomanip>
void Add(std::string fileName, YAML::Node config)
{
std::ofstream fout(fileName, std::ios::app);
fout << std::endl << config;
fout.close();
}
void Change(std::string fileName, YAML::Node config)
{
std::ofstream fout(fileName);
fout << std::endl << config;
fout.close();
}
void Query(YAML::Node config)
{
//Node是一个类map结构
//enum value { Undefined, Null, Scalar, Sequence, Map };
switch (config.Type() )
{
case 0:
case 1:
break;
case 2: //scalar
{
std::cout << config.as<std::string>() << std::endl;
break;
}
case 3: //sequence
{
std::cout << std::endl;
for (auto it_1 : config)
{
std::cout << std::setw(3)<<"-";
Query(it_1);
}
break;
}
case 4: //map
{
std::cout << std::endl;
for (auto it_1 : config)
{
std::cout << std::setw(5) << it_1.first.as<std::string>() << ":";
YAML::Node NodeNext = it_1.second;
Query(NodeNext);
}
break;
}
default:
break;
}
}
int main()
{
YAML::Node config;
std::string fileName = "file1.yml";
//insert
config["skills"]["eat"] = 10; //< 修改格式1
config["name"] = "hening"; //< 修改格式2
config["hobby"].push_back("football");
config["hobby"].push_back("basketball");
Add(fileName, config);
config.reset();
//change
config = YAML::LoadFile(fileName);
config["blood"] = 15;
Change(fileName, config);
//Query
Query(config);
//Delete
config["skills"].remove("eat");
system("pause");
return 0;
}
将yaml文件与控制台查询结果做对比,可发现两者结果一致。
唯一的缺点是输出时,当node节点为map类型,无法有效区别层次,可添加循环嵌套实现。