1. 程式人生 > >How to Access Data in a Property Tree

How to Access Data in a Property Tree

clas 代碼 3.0 float itl compute iter () find

在屬性樹裏怎麽訪問數據?

屬性樹類似於(幾乎是)一個標準容器,其值類型為pair。它具有通常的成員函數,如insert、push_back、find、erase等,當然可以使用這些函數來填充和訪問樹。例如,下面的代碼添加了關鍵詞為“pi”的數據(幾乎)等於數學pi值:

  1. ptree pt;
  2. pt.push_back(ptree::value_type("pi", ptree("3.14159")));
為了求出pi的值,我們可以這樣做:
  1. ptree::const_iterator it = pt.find("pi");
  2. double pi = boost::lexical_cast<double>
    (it->second.data());
這裏也要提示下:這裏使用了一個非常好用的擴展類型轉化,convert的庫的函數:lexical_cast
這看起來很麻煩,如果pi值不存儲在樹頂附近,我們會更關心錯誤。幸運的是,還有另一種正確的方法:
  1. ptree pt;
  2. pt.put("pi", 3.14159); // put double
  3. double pi = pt.get<double>("pi"); // get double
沒有比這更簡單的了。基本上,有2個家庭成員函數,get和put,這允許直觀地訪問存儲在樹中的數據(直接的孩子或不是)。


三種方式獲取數據


get有三個版本:get、get(默認值版本)和get_optional,這與失敗處理策略不同。所有版本都使用路徑說明符,它決定了在哪個鍵中搜索值。它可以是單個鍵,也可以是鍵的路徑,其中路徑元素以特殊字符(.)分隔。(如果沒有具體說明)。例如debug.logging.errorlevel 可能是一個帶點作為分隔符的有效路徑。
1.拋出異常的處理
  1. ptree pt;
  2. /* ... */
  3. float v = pt.get<float>("a.path.to.float.value");

此調用將定位樹中的適當節點,並嘗試將其數據字符串轉換為浮點值。如果失敗,則拋出異常。如果路徑不存在,它將是ptree_bad_path異常。如果值不能被翻譯,它將是ptree_bad_data。它們都源於ptree_error,以使普通處理成為可能。
2.有默認值的版本
  1. ptree pt
    ;
  2. /* ... */
  3. float v = pt.get("a.path.to.float.value", -1.f);
它將執行與上面相同的操作,但是如果失敗,它將返回第二個參數指定的默認值(這裏-1.f)而不是拋出。這在通常情況下是非常有用的,因為人們想要省略一些鍵。請註意,在這裏通常沒有必要的類型規範,因為類型是由默認值參數決定的。
3.可選的版本
  1. ptree pt;
  2. /* ... */
  3. boost::optional<float> v = pt.get_optional<float>("a.path.to.float.value");
這個版本使用boost::optional來處理提取失敗。在成功的提取上,它將返回boost::optional的初始化值。否則,它將返回未初始化的boost::optional
要從這棵樹(不是一些子鍵)中檢索值,可以使用get_value、get_value (default-value version)和get_value_optional。它們具有相同的語義以獲得函數,但它們不接受路徑參數。不要調用get和empty路徑,因為它將嘗試以空名稱提取子鍵的內容。

如果要使用除默認之外的分隔,您需要顯式地構造路徑對象。ptree的路徑類型是string_path實例化,因此最容易引用它的方法是ptree::path_type。這樣你就可以使用在他們的key上有(.)的樹【也就是,key裏有點的路徑】:
  1. typedef ptree::path_type path;
  2. pt.get<float>(path("p.a.t.h/t.o/v.a.l.u.e", ‘/‘));
  3. pt.get(path("p.a.t.h/t.o/v.a.l.u.e", ‘/‘), 0, NULL);
  4. pt.get_optional<std::string>(path("p.a.t.h/t.o/v.a.l.u.e", ‘/‘));
可以看到,這裏使用的是"/"來作為分隔符,原因,很簡單,你在key你有了點(.),就不能再使用點來作為分隔了,我們需要使用新的字符!
註意:在PropertyTree的預發布版本中存在的get和get_optional的特殊重載已被刪除。這是因為重載與使用每個調用的數據轉換器沖突。

Two Ways of Putting Data

同樣的道理,有獲得值,就有添加值!get和put是一對,在添加數據時不需要處理丟失的值。如果提供的值不能轉換為樹的數據類型,則函數將拋出ptree_bad_data
  1. ptree pt;
  2. pt.put("a.path.to.float.value", 3.14f);
  3. // Overwrites the value
  4. pt.put("a.path.to.float.value", 2.72f);
  5. // Adds a second node with the new value.
  6. pt.add("a.path.to.float.value", 3.14f);

調用put將在指定的路徑中插入一個新值,以便調用來指定相同的路徑將檢索它。此外,在路徑遍歷過程中,put將插入任何丟失的路徑元素。例如,調用put("key1.key2.key3", 3.14f),在一個空的樹上,將插入三個新子:key1, key1.key2; key1.key2.key3。最後一個將接收到一個字符串“3.14”作為數據,而前兩個將會有空的數據字符串。總是在現有序列的後面插入新的鍵
put和add之間的區別是,put將覆蓋現有的值,如果有的話,add將創建一個新的節點來保存該值,即使指定的路徑引用了現有的節點與get_value類似,還有一個put_value函數。它不接受路徑:
ptree pt;
pt.put_value(3.14f);



null

How to Access Data in a Property Tree