yaml-cpp YAML格式處理庫的介紹和使用(面向業務程式設計-檔案格式處理)

2023-04-05 12:00:35

yaml-cpp YAML格式處理庫的介紹和使用(面向業務程式設計-檔案格式處理)

YAML格式介紹

YAML的格式介紹,有關ini、json和xml或許很多人已經很瞭解了,但是關於YAML,還有許多人不瞭解。YAML被設計成更適合人類閱讀(我想正因為如此,所以相對來說更靈活,就導致到使用的時候很多人會覺得它看起來並不嚴謹)。它的想法類似於Python,去掉了括號和標籤,看起來就比較簡潔。廢話不多說,直接開搞

下面這篇文章有介紹它的一些語法規則

https://zhuanlan.zhihu.com/p/145173920

官網地址:https://yaml.org/

C++關於YAML的庫好像找來找去就只有yaml-cpp這個庫,並且官網也展示了這個庫

yaml-cpp

yaml-cpp是一個C++的YAML解析處理庫,符合YAML1.2規範

倉庫地址:

https://github.com/jbeder/yaml-cpp

好了,正式開始使用yaml-cpp

以下使用範例均參考自知乎文章https://zhuanlan.zhihu.com/p/96831410

引入標頭檔案

#include "yaml-cpp/yaml.h"
#include <iostream>

宣告一個節點

首先,我們宣告一個節點

YAML::Node node;

節點宣告之後是null型別可以用node.IsNull()判斷

鍵值對

node["key"] = "value";

直接用[]運運算元可以像map一樣存取

上面這樣表示將鍵key的值設定為value

node["number"] = 255;

也可以賦值為數位,可以用node.IsMap()去檢視當前是不是Map型別

Sequence型別(其實就是陣列)

node["seq"].push_back("first element");
node["seq"].push_back("second element");

上面程式碼錶示seq是一個陣列,陣列的內容有first element和second element。

不給名字的Sequence

YAML::Node node2;  
node2.push_back("first item");
node2.push_back("second_item");
node2.push_back("third_item");

當不給下標,直接push_back的時候,node2就是一個Sequence型別

插入一個陣列

當然除了字串,也可以插入一個陣列

std::vector<int> v = {1,3,5,7,9};
node.push_back(v);

插入的陣列即是一個Sequence,Sequence型別可以用node.IsSequence()來判斷是不是Sequence

存取Sequence型別

對於Sequence型別可以用下標存取

assert(node2[0].as<std::string>() == "first item");

也可以用迭代器存取

for(auto it = node2.begin();; it != node2.end(); it++)
    std::cout << *(it) << std::endl;

將一個節點作為另一個節點的子項

 node["node2"] = node2;

給key設定別名,類似於指標

node["pointer_to_first_element"] = node["seq"][0];
// 可以用pointer_to_first_element來存取seq的0號節點
node["pointer_to_first_element"] = "hahaha";

刪除一個節點

指定一個node來刪除這個節點

node.remove(node["seq"][0]);

也可以指定一個key來刪除一個節點,注意這個刪除的是指標節點,而非原節點

node.remove("pointer_to_first_element");

怎麼讀取解析

yaml-cpp可以支援流讀取

try {
    std::ifstream fin("test.yaml");
    YAML::Parser parser(fin);
    YAML::Node doc;
    parser.GetNextDocument(doc);
    // do stuff
} catch(YAML::ParserException& e) {
    std::cout << e.what() << "\n";
}

怎麼寫入到檔案

同樣使用流的方式寫入到檔案

std::ofstream file("test.yaml");
file << node <<std::endl;

更多相關操作,或者使用Emitting操作,可以參考官方倉庫的docs

https://github.com/jbeder/yaml-cpp/tree/master/docs

以庫的形式新增到專案中

本文為作者原創文章,轉載請註明出處:https://www.cnblogs.com/nbtech/p/use_yaml-cpp_library.html

yaml-cpp以庫的形式新增到專案中

mkdir UseYaml-cppProject && cd UseYaml-cppProject
git clone https://github.com/jbeder/yaml-cpp.git
vim CMakeLists.txt

CMakeLists.txt檔案內容如下

# CMakeLists.txt example,by https://www.cnblogs.com/nbtech/p/use_yaml-cpp_library.html
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(useYaml-cpp LANGUAGES CXX)

# lib yaml-cpp
include_directories(yaml-cpp/include)
add_subdirectory(yaml-cpp lib)

# executable output
add_executable(useYaml-cpp main.cpp)
target_link_libraries(useYaml-cpp yaml-cpp)

CMakeLists.txt檔案就不多解釋了,add_executable需要加到add_subdirectory的下面

在專案目錄再新建一個main.cpp檔案,main.cpp檔案內容如下

#include <iostream>
#include "yaml-cpp/yaml.h"

int main() {
    YAML::Node node;
    node["number"] = 255;
    node["string"] = "sample str";

    YAML::Node subNode;
    subNode.push_back("element 1");
    subNode.push_back("element 2");
    node["sub"] = subNode;

    std::cout << node << std::endl;
}

寫完之後建立目錄並編譯

mkdir build && cd build
cmake .. && make

編譯後生成useYaml-cpp檔案,執行後輸出結果如下:

number: 255
string: sample str
sub:
  - element 1
  - element 2

交叉編譯?

有時候我們希望它可以跨平臺,那麼只需要在cmake設定的時候指定交叉編譯工具即可

cmake -D CMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ ..