C++ Boost PropertyTree示例超詳細(xì)講解
一、提要
借助類(lèi) boost::property_tree::ptree,Boost.PropertyTree 提供了一個(gè)樹(shù)結(jié)構(gòu)來(lái)存儲(chǔ)鍵/值對(duì)。樹(shù)形結(jié)構(gòu)意味著一個(gè)樹(shù)干存在許多分支,其中有許多樹(shù)枝。文件系統(tǒng)是樹(shù)結(jié)構(gòu)的一個(gè)很好的例子。文件系統(tǒng)有一個(gè)帶有子目錄的根目錄,這些子目錄本身可以有子目錄等等。
二、應(yīng)用示例
要使用 boost::property_tree::ptree,請(qǐng)包含頭文件 boost/property_tree/ptree.hpp。這是一個(gè)主頭文件,因此 Boost.PropertyTree 不需要包含其他頭文件。
示例 25.1。訪問(wèn) boost::property_tree::ptree 中的數(shù)據(jù)
#include <boost/property_tree/ptree.hpp> #include <iostream> using boost::property_tree::ptree; int main() { ptree pt; pt.put("C:.Windows.System", "20 files"); ptree &c = pt.get_child("C:"); ptree &windows = c.get_child("Windows"); ptree &system = windows.get_child("System"); std::cout << system.get_value<std::string>() << '\n'; }
example25.1 使用 boost::property_tree::ptree 來(lái)存儲(chǔ)目錄的路徑。這是通過(guò)調(diào)用 put() 來(lái)完成的。此成員函數(shù)需要兩個(gè)參數(shù),因?yàn)?boost::property_tree::ptree 是一個(gè)保存鍵/值對(duì)的樹(shù)結(jié)構(gòu)。樹(shù)不僅由樹(shù)枝和樹(shù)枝組成,還必須為每個(gè)樹(shù)枝和樹(shù)枝分配一個(gè)值。在示例 25.1 中,該值為“20 個(gè)文件”。
傳遞給 put() 的第一個(gè)參數(shù)更有趣。它是一個(gè)目錄的路徑。但是,它不使用反斜杠,這是 Windows 上常見(jiàn)的路徑分隔符。它使用點(diǎn)。
您需要使用點(diǎn),因?yàn)樗?Boost.PropertyTree 期望的鍵的分隔符。參數(shù)“C:.Windows.System”告訴 pt 創(chuàng)建一個(gè)名為 C: 的分支,其中一個(gè)名為 Windows 的分支具有另一個(gè)名為 System 的分支。點(diǎn)創(chuàng)建分支的嵌套結(jié)構(gòu)。如果“C:\Windows\System”作為參數(shù)傳遞,pt 將只有一個(gè)名為 C:\Windows\System 的分支。
調(diào)用 put() 后,訪問(wèn) pt 以讀取存儲(chǔ)的值“20 個(gè)文件”并將其寫(xiě)入標(biāo)準(zhǔn)輸出。這是通過(guò)從一個(gè)分支跳轉(zhuǎn)到另一個(gè)分支 - 或從一個(gè)目錄跳轉(zhuǎn)到另一個(gè)目錄來(lái)完成的。
要訪問(wèn)子分支,您可以調(diào)用 get_child(),它會(huì)返回對(duì)與調(diào)用 get_child() 相同類(lèi)型的對(duì)象的引用。在示例 25.1 中,這是對(duì) boost::property_tree::ptree 的引用。因?yàn)槊總€(gè)分支都可以有子分支,并且由于高低分支之間沒(méi)有結(jié)構(gòu)差異,所以使用相同的類(lèi)型。
第三次調(diào)用 get_child() 檢索 boost::property_tree::ptree,它表示目錄 System。調(diào)用 get_value() 以讀取在示例開(kāi)頭使用 put() 存儲(chǔ)的值。
請(qǐng)注意,get_value() 是一個(gè)函數(shù)模板。您將返回值的類(lèi)型作為模板參數(shù)傳遞。這樣 get_value() 可以進(jìn)行自動(dòng)類(lèi)型轉(zhuǎn)換。
示例 25.2。訪問(wèn) basic_ptree<std::string, int> 中的數(shù)據(jù)
#include <boost/property_tree/ptree.hpp> #include <utility> #include <iostream> int main() { typedef boost::property_tree::basic_ptree<std::string, int> ptree; ptree pt; pt.put(ptree::path_type{"C:\\Windows\\System", '\\'}, 20); pt.put(ptree::path_type{"C:\\Windows\\Cursors", '\\'}, 50); ptree &windows = pt.get_child(ptree::path_type{"C:\\Windows", '\\'}); int files = 0; for (const std::pair<std::string, ptree> &p : windows) files += p.second.get_value<int>(); std::cout << files << '\n'; }
與示例 25.1 相比,示例 25.2 有兩個(gè)變化。這些更改是為了更輕松地保存目錄路徑和目錄中的文件數(shù)量。首先,路徑在傳遞給 put() 時(shí)使用反斜杠作為分隔符。其次,文件的數(shù)量存儲(chǔ)為 int。
默認(rèn)情況下,Boost.PropertyTree 使用點(diǎn)作為鍵的分隔符。如果您需要使用其他字符(例如反斜杠)作為分隔符,則不要將鍵作為字符串傳遞給 put()。相反,您將其包裝在 boost::property_tree::ptree::path_type 類(lèi)型的對(duì)象中。這個(gè)類(lèi)的構(gòu)造函數(shù)依賴于 boost::property_tree::ptree,它的第一個(gè)參數(shù)是鍵,第二個(gè)參數(shù)是分隔符。這樣,您可以使用 C:\Windows\System 等路徑,如示例 25.2 所示,而無(wú)需將反斜杠替換為點(diǎn)。
boost::property_tree::ptree 基于類(lèi)模板 boost::property_tree::basic_ptree。因?yàn)殒I和值通常是字符串,所以 boost::property_tree::ptree 是預(yù)定義的。但是,您可以將 boost::property_tree::basic_ptree 用于鍵和值的不同類(lèi)型。示例 25.2 中的樹(shù)使用 int 來(lái)存儲(chǔ)目錄中的文件數(shù),而不是字符串。
boost::property_tree::ptree 提供成員函數(shù) begin() 和 end()。但是,boost::property_tree::ptree 只允許您在一個(gè)級(jí)別上迭代分支。示例 25.2 遍歷 C:\Windows 的子目錄。您無(wú)法讓迭代器遍歷所有級(jí)別的所有分支。
示例 25.2 中的 for 循環(huán)讀取 C:\Windows 的所有子目錄中的文件數(shù)以計(jì)算總數(shù)。因此,該示例顯示 70。該示例不直接訪問(wèn) ptree 類(lèi)型的對(duì)象。相反,它迭代類(lèi)型為 std::pair<std::string, ptree> 的元素。 first 包含當(dāng)前分支的鍵。即示例 25.2 中的系統(tǒng)和游標(biāo)。第二個(gè)提供對(duì) ptree 類(lèi)型對(duì)象的訪問(wèn),它表示可能的子目錄。在示例中,僅讀取分配給 System 和 Cursors 的值。如示例 25.1,調(diào)用成員函數(shù) get_value()。
boost::property_tree::ptree 只存儲(chǔ)當(dāng)前分支的值,而不是它的鍵。您可以使用 get_value() 獲取值,但沒(méi)有獲取密鑰的成員函數(shù)。密鑰存儲(chǔ)在 boost::property_tree::ptree 上一級(jí)。這也解釋了為什么 for 循環(huán)會(huì)迭代 std::pair<std::string, ptree> 類(lèi)型的元素。
示例 25.3。使用翻譯器訪問(wèn)數(shù)據(jù)
#include <boost/property_tree/ptree.hpp> #include <boost/optional.hpp> #include <iostream> #include <cstdlib> struct string_to_int_translator { typedef std::string internal_type; typedef int external_type; boost::optional<int> get_value(const std::string &s) { char *c; long l = std::strtol(s.c_str(), &c, 10); return boost::make_optional(c != s.c_str(), static_cast<int>(l)); } }; int main() { typedef boost::property_tree::iptree ptree; ptree pt; pt.put(ptree::path_type{"C:\\Windows\\System", '\\'}, "20 files"); pt.put(ptree::path_type{"C:\\Windows\\Cursors", '\\'}, "50 files"); string_to_int_translator tr; int files = pt.get<int>(ptree::path_type{"c:\\windows\\system", '\\'}, tr) + pt.get<int>(ptree::path_type{"c:\\windows\\cursors", '\\'}, tr); std::cout << files << '\n'; }
示例 25.3 與 boost::property_tree::iptree 一起使用來(lái)自 Boost.PropertyTree 的另一個(gè)預(yù)定義樹(shù)。通常,此類(lèi)型的行為類(lèi)似于 boost::property_tree::ptree。唯一的區(qū)別是 boost::property_tree::iptree 不區(qū)分大小寫(xiě)。例如,使用 C:\Windows\System 鍵存儲(chǔ)的值可以用 c:\windows\system 讀取。
與示例 25.1 不同,get_child() 不會(huì)被多次調(diào)用來(lái)訪問(wèn)子分支。正如 put() 可用于將值直接存儲(chǔ)在子分支中一樣,子分支中的值也可以使用 get() 讀取。鍵的定義方式相同——例如使用 boost::property_tree::iptree::path_type。
與 get_value() 一樣,get() 是一個(gè)函數(shù)模板。您必須將返回值的類(lèi)型作為模板參數(shù)傳遞。 Boost.PropertyTree 進(jìn)行自動(dòng)類(lèi)型轉(zhuǎn)換。
為了轉(zhuǎn)換類(lèi)型,Boost.PropertyTree 使用翻譯器。該庫(kù)提供了一些開(kāi)箱即用的翻譯器,它們基于流并且可以自動(dòng)轉(zhuǎn)換類(lèi)型。
示例 25.3 與 boost::property_tree::iptree 一起使用來(lái)自 Boost.PropertyTree 的另一個(gè)預(yù)定義樹(shù)。通常,此類(lèi)型的行為類(lèi)似于 boost::property_tree::ptree。唯一的區(qū)別是 boost::property_tree::iptree 不區(qū)分大小寫(xiě)。例如,使用 C:\Windows\System 鍵存儲(chǔ)的值可以用 c:\windows\system 讀取。
與示例 25.1 不同,get_child() 不會(huì)被多次調(diào)用來(lái)訪問(wèn)子分支。正如 put() 可用于將值直接存儲(chǔ)在子分支中一樣,子分支中的值也可以使用 get() 讀取。鍵的定義方式相同——例如使用 boost::property_tree::iptree::path_type。
與 get_value() 一樣,get() 是一個(gè)函數(shù)模板。您必須將返回值的類(lèi)型作為模板參數(shù)傳遞。 Boost.PropertyTree 進(jìn)行自動(dòng)類(lèi)型轉(zhuǎn)換。
為了轉(zhuǎn)換類(lèi)型,Boost.PropertyTree 使用翻譯器。該庫(kù)提供了一些開(kāi)箱即用的翻譯器,它們基于流并且可以自動(dòng)轉(zhuǎn)換類(lèi)型。
#include <boost/property_tree/ptree.hpp> #include <utility> #include <iostream> using boost::property_tree::ptree; int main() { ptree pt; pt.put("C:.Windows.System", "20 files"); boost::optional<std::string> c = pt.get_optional<std::string>("C:"); std::cout << std::boolalpha << c.is_initialized() << '\n'; pt.put_child("D:.Program Files", ptree{"50 files"}); pt.add_child("D:.Program Files", ptree{"60 files"}); ptree d = pt.get_child("D:"); for (const std::pair<std::string, ptree> &p : d) std::cout << p.second.get_value<std::string>() << '\n'; boost::optional<ptree&> e = pt.get_child_optional("E:"); std::cout << e.is_initialized() << '\n'; }
示例 25.3 定義了轉(zhuǎn)換器 string_to_int_translator,它將 std::string 類(lèi)型的值轉(zhuǎn)換為 int。翻譯器作為附加參數(shù)傳遞給 get()。因?yàn)榉g器只是用來(lái)閱讀的,所以它只定義了一個(gè)成員函數(shù),get_value()。如果您也想使用翻譯器進(jìn)行寫(xiě)作,那么您需要定義一個(gè)成員函數(shù) put_value(),然后將翻譯器作為附加參數(shù)傳遞給 put()。
get_value() 返回 pt 中使用的類(lèi)型的值。但是,由于類(lèi)型轉(zhuǎn)換并不總是成功,因此使用了 boost::optional。如果示例 25.3 中存儲(chǔ)的值無(wú)法使用 std::strtol() 轉(zhuǎn)換為 int,則將返回 boost::optional 類(lèi)型的空對(duì)象。
請(qǐng)注意,翻譯人員還必須定義 internal_type 和 external_type 兩種類(lèi)型。如果需要在存儲(chǔ)數(shù)據(jù)時(shí)進(jìn)行類(lèi)型轉(zhuǎn)換,請(qǐng)定義類(lèi)似于 get_value() 的 put_value()。
如果您修改示例 25.3 以存儲(chǔ)值“20”而不是值“20 個(gè)文件”,則可以調(diào)用 get_value() 而無(wú)需傳遞翻譯器。 Boost.PropertyTree 提供的翻譯器可以將 std::string 轉(zhuǎn)換為 int。但是,只有在可以轉(zhuǎn)換整個(gè)字符串時(shí),類(lèi)型轉(zhuǎn)換才會(huì)成功。字符串不能包含任何字母。因?yàn)橹灰址詳?shù)字開(kāi)頭,std::strtol() 就可以進(jìn)行類(lèi)型轉(zhuǎn)換,因此示例 25.3 中使用了更自由的轉(zhuǎn)換器 string_to_int_translator。
示例 25.4。 boost::property_tree::ptree 的各種成員函數(shù)
如果要讀取鍵的值,可以調(diào)用成員函數(shù) get_optional(),但不確定該鍵是否存在。 get_optional() 返回 boost::optional 類(lèi)型對(duì)象中的值。如果未找到密鑰,則該對(duì)象為空。否則,get_optional() 的工作方式與 get() 相同。
看起來(lái) put_child() 和 add_child() 與 put() 相同。不同之處在于 put() 只創(chuàng)建一個(gè)鍵/值對(duì),而 put_child() 和 add_child() 插入整個(gè)子樹(shù)。請(qǐng)注意,類(lèi)型為 boost::property_tree::ptree 的對(duì)象作為第二個(gè)參數(shù)傳遞給 put_child() 和 add_child()。
put_child() 和 add_child() 之間的區(qū)別在于 put_child() 會(huì)在該鍵已經(jīng)存在時(shí)訪問(wèn)該鍵,而 add_child() 總是將一個(gè)新鍵插入到樹(shù)中。這就是示例 25.4 中的樹(shù)有兩個(gè)名為“D:.Program Files”的鍵的原因。根據(jù)用例,這可能會(huì)令人困惑。如果一棵樹(shù)代表一個(gè)文件系統(tǒng),則不應(yīng)有兩條相同的路徑。如果您不想在樹(shù)中重復(fù),則必須避免插入相同的鍵。
示例 25.4 顯示了 for 循環(huán)中“D:”下方鍵的值。該示例將 50 個(gè)文件和 60 個(gè)文件寫(xiě)入標(biāo)準(zhǔn)輸出,這證明有兩個(gè)相同的鍵,稱(chēng)為“D:.Program Files”。
示例 25.4 中引入的最后一個(gè)成員函數(shù)是 get_child_optional()。此函數(shù)的使用方式與 get_child() 類(lèi)似。 get_child_optional() 返回 boost::optional 類(lèi)型的對(duì)象。如果您不確定密鑰是否存在,則調(diào)用 boost::optional。
示例 25.5。以 JSON 格式序列化 boost::property_tree::ptree
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/json_parser.hpp> #include <iostream> using namespace boost::property_tree; int main() { ptree pt; pt.put("C:.Windows.System", "20 files"); pt.put("C:.Windows.Cursors", "50 files"); json_parser::write_json("file.json", pt); ptree pt2; json_parser::read_json("file.json", pt2); std::cout << std::boolalpha << (pt == pt2) << '\n'; }
Boost.PropertyTree 不僅僅提供結(jié)構(gòu)來(lái)管理內(nèi)存中的數(shù)據(jù)。從示例 25.5 中可以看出,該庫(kù)還提供了將 boost::property_tree::ptree 保存在文件中并從文件中加載的函數(shù)。
頭文件 boost/property_tree/json_parser.hpp 提供對(duì)函數(shù) boost::property_tree::json_parser::write_json() 和 boost::property_tree::json_parser::read_json() 的訪問(wèn)。這些函數(shù)可以保存和加載以 JSON 格式序列化的 boost::property_tree::ptree。這樣您就可以支持 JSON 格式的配置文件。
如果要調(diào)用將 boost::property_tree::ptree 存儲(chǔ)在文件中或從文件中加載的函數(shù),則必須包含頭文件,例如 boost/property_tree/json_parser.hpp。僅包含 boost/property_tree/ptree.hpp 是不夠的。
除了函數(shù) boost::property_tree::json_parser::write_json() 和 boost::property_tree::json_parser::read_json() 之外,Boost.PropertyTree 還提供了其他數(shù)據(jù)格式的函數(shù)。您使用來(lái)自 boost/property_tree/ini_parser.hpp 的 boost::property_tree::ini_parser::write_ini() 和 boost::property_tree::ini_parser::read_ini() 來(lái)支持 INI 文件。使用來(lái)自 boost/property_tree/xml_parser.hpp 的 boost::property_tree::xml_parser::write_xml() 和 boost::property_tree::xml_parser::read_xml(),可以以 XML 格式加載和存儲(chǔ)數(shù)據(jù)。使用來(lái)自 boost/property_tree/info_parser.hpp 的 boost::property_tree::info_parser::write_info() 和 boost::property_tree::info_parser::read_info(),您可以訪問(wèn)另一種為序列化 Boost 中的樹(shù)而開(kāi)發(fā)和優(yōu)化的格式.PropertyTree。
任何受支持的格式都不能保證 boost::property_tree::ptree 在保存和重新加載后看起來(lái)是一樣的。例如,JSON 格式可能會(huì)丟失類(lèi)型信息,因?yàn)?boost::property_tree::ptree 無(wú)法區(qū)分 true 和“true”。類(lèi)型始終相同。即使各種函數(shù)可以輕松保存和加載 boost::property_tree::ptree,但不要忘記 Boost.PropertyTree 并不完全支持這些格式。該庫(kù)的主要重點(diǎn)是結(jié)構(gòu) boost::property_tree::ptree,而不是支持各種數(shù)據(jù)格式。
練習(xí)
創(chuàng)建一個(gè)加載此 JSON 文件并將所有動(dòng)物的名稱(chēng)寫(xiě)入標(biāo)準(zhǔn)輸出的程序。如果“all”設(shè)置為 true,則程序不僅應(yīng)將所有動(dòng)物的名稱(chēng),而且應(yīng)將所有屬性寫(xiě)入標(biāo)準(zhǔn)輸出:
{ "animals": [ { "name": "cat", "legs": 4, "has_tail": true }, { "name": "spider", "legs": 8, "has_tail": false } ], "log": { "all": true } }
到此這篇關(guān)于C++ Boost PropertyTree示例超詳細(xì)講解的文章就介紹到這了,更多相關(guān)C++ Boost PropertyTree內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C 語(yǔ)言環(huán)境設(shè)置詳細(xì)講解
本文主要介紹C 語(yǔ)言環(huán)境設(shè)置,在不同的系統(tǒng)平臺(tái)上,C語(yǔ)言的環(huán)境設(shè)置不同,這里幫大家整理了Liunx, UNIX,Windows 上安裝C語(yǔ)言環(huán)境,有開(kāi)始學(xué)習(xí)C語(yǔ)言的朋友可以參考下2016-08-08C語(yǔ)言中數(shù)據(jù)結(jié)構(gòu)之鏈表歸并排序?qū)嵗a
這篇文章主要介紹了C語(yǔ)言中數(shù)據(jù)結(jié)構(gòu)之鏈表歸并排序?qū)嵗a的相關(guān)資料,需要的朋友可以參考下2017-05-05基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的掃雷游戲
這篇文章主要為大家詳細(xì)介紹了基于C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的掃雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10C++采用openfilename打開(kāi)文件對(duì)話框用法實(shí)例
這篇文章主要介紹了C++采用openfilename打開(kāi)文件對(duì)話框用法實(shí)例,是C++文件操作中非常實(shí)用的技巧,需要的朋友可以參考下2014-10-10C++開(kāi)發(fā)在IOS環(huán)境下運(yùn)行的LRUCache緩存功能
本文著重介紹如何在XCODE中,通過(guò)C++開(kāi)發(fā)在IOS環(huán)境下運(yùn)行的緩存功能。算法基于LRU,最近最少使用,需要的朋友可以參考下2012-11-11C語(yǔ)言scanf語(yǔ)句吃掉回車(chē)或者空格問(wèn)題及解決
這篇文章主要介紹了C語(yǔ)言scanf語(yǔ)句吃掉回車(chē)或者空格問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11C語(yǔ)言實(shí)現(xiàn)猜數(shù)字游戲的兩種方法
猜數(shù)字小游戲是我們大多數(shù)人學(xué)習(xí)C語(yǔ)言時(shí)都會(huì)了解到的一個(gè)有趣的C語(yǔ)言小游戲,本文就詳細(xì)的介紹一下,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01詳解如何用alpine鏡像做一個(gè)最小的鏡像并運(yùn)行c++程序
這篇文章主要介紹了詳解如何用alpine鏡像做一個(gè)最小的鏡像并運(yùn)行c++程序,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10