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()等转化

打赏 赞(9)
微信
支付宝
微信二维码图片

微信扫描二维码打赏

支付宝二维码图片

支付宝扫描二维码打赏

发表评论

邮箱地址不会被公开。 必填项已用*标注