本文使用 C++ 库 yaml-cpp 对 yaml 文件进行解析。
下载编译
下载地址:https://github.com/jbeder/yaml-cpp/releases/tag/yaml-cpp-0.6.3 。 文件名为:yaml-cpp-yaml-cpp-0.6.3.zip。
解压,进入库目录,创建build目录。执行:
在build目录生成 libyaml-cpp.a 文件。将其与源码的 include 目录拷贝至工程目录,在编译时进行链接即可。
注:cmake须3.0以上。
测试
yaml 配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| # yaml测试样例 # null 或 NULL 为关键字,不能写
# 名称 # 字符串 name: conf file
# 版本 # 如按浮点,2.0会转换成2 # 如按字符串,保留原样 version: 2.0
# 布尔类,转换为1或0 need: true
# 时间 time: 2020-10-03T09:21:13
empty: nul
# 对象 # 加双引号会转义\n,即会换行 my: name: late \n lee name1: "late \n lee" age: 99 # 块 text: | hello world!
# 数组 fruit: - apple - apple1 - apple2 - apple3 - apple4 - apple5
# 多级数组 multi: sta: - 110 210 ddd 99 - 133 135 1 2 1588 1509 - 310-410 - 333-444
|
该示例基本涵盖了大部分的 yaml 格式。包括:字符串,数值、数组、多级map。
测试代码
测试代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| #include <iostream> #include "yaml-cpp/yaml.h"
using namespace std;
int main(int argc,char** argv) { YAML::Node config; // 当文件不存在或yaml格式出错时,抛异常 try { config = YAML::LoadFile("config.yaml"); } catch (...) { printf("error loading file, yaml file error or not exist.\n"); return 0; }
// 获取类型 for (YAML::const_iterator it = config.begin(); it != config.end(); ++it) { std::string key = it->first.as<std::string>(); YAML::Node value = it->second; switch (value.Type()) { case YAML::NodeType::Scalar: printf("key: %s scalar\n", key.c_str()); break; case YAML::NodeType::Sequence: printf("key: %s Sequence\n", key.c_str()); cout << "seq: " << value << endl; break; case YAML::NodeType::Map: printf("key: %s Map\n", key.c_str()); break; case YAML::NodeType::Null: printf("key: %s Null\n", key.c_str()); break; case YAML::NodeType::Undefined: printf("key: %s Undefined\n", key.c_str()); break; // etc. } }
// 顶层 cout << "version:" << config["version"].as<float>() << endl; cout << "version(str):" << config["version"].as<string>() << endl; cout << "need:" << config["need"].as<bool>() << endl; // 输出值为1 cout << "time:" << config["time"].as<string>() << endl; cout << "empty:" << config["empty"].as<string>() << endl; try { printf("sizeof array: %d\n", (int)config["fruit"].size()); //cout << "fruit1:\n" << config["fruit"] << endl; // 此处返回 Node // 索引方式取 //for (int i = 0; i < (int)config["fruit"].size(); i++) //{ // cout << "fruit2: " << config["fruit"][i].as<string>() << endl; //} // 单个取 for (auto item : config["fruit"]) { cout << "fruit3: " << item.as<string>() << endl; } } catch(...) { printf("fruit not ok.\n"); } try { printf("new sta: \n"); for (auto item : config["multi"]["sta"]) { printf("%s \n", item.as<string>().c_str()); } printf("\n"); } catch (...) { //printf("key not exist...\n"); //return 0; } // 对于不存在的key,似乎只能用try try { cout << "bad:" << config["bad"].as<int>() << endl; } catch (...) { printf("key bad not exist...\n"); //return 0; } cout << "text:" << config["text"].as<string>() << endl; // 有两层 printf("name: %s \nname1: %s \nage: %d\n", config["my"]["name"].as<string>().c_str(), config["my"]["name1"].as<string>().c_str(), config["my"]["age"].as<int>());
return 0; }
|
输出结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| ./a.out key: name scalar key: version scalar key: need scalar key: time scalar key: empty scalar key: my Map key: text scalar key: fruit Sequence seq: - apple - apple1 - apple2 - apple3 - apple4 - apple5 key: multi Map version:2 version(str):2.0 need:1 time:2020-10-03T09:21:13 empty:nul sizeof array: 6 fruit3: apple fruit3: apple1 fruit3: apple2 fruit3: apple3 fruit3: apple4 fruit3: apple5 new sta: 110 210 ddd 99 133 135 1 2 1588 1509 310-410 333-444
key bad not exist... text:hello world!
name: late \n lee name1: late lee age: 99
|
结果说明
1、name: "late \n lee"
输出会换行。而 name: late \n lee
则会原样输出。
2、参数的值不能为 null 或 NULL,但可以为nul。
3、如果字段不存在或非法,会直接报段错误,因此需要用 try catch
读取。