在属性树里怎么访问数据?
属性树类似于(几乎是)一个标准容器,其值类型为pair。它具有通常的成员函数,如insert、push_back、find、erase等,当然可以使用这些函数来填充和访问树。例如,下面的代码添加了关键词为“pi”的数据(几乎)等于数学pi值:
ptree pt;
pt.push_back(ptree::value_type("pi", ptree("3.14159")));
为了求出pi的值,我们可以这样做:
ptree::const_iterator it = pt.find("pi");
double pi = boost::lexical_cast<double>(it->second.data());
这里也要提示下:这里使用了一个非常好用的扩展类型转化,convert的库的函数:lexical_cast
这看起来很麻烦,如果pi值不存储在树顶附近,我们会更关心错误。幸运的是,还有另一种正确的方法:
ptree pt;
pt.put("pi", 3.14159); // put double
double pi = pt.get<double>("pi"); // get double
没有比这更简单的了。基本上,有2个家庭成员函数,get和put,这允许直观地访问存储在树中的数据(直接的孩子或不是)。
三种方式获取数据
get有三个版本:get、get(默认值版本)和get_optional,这与失败处理策略不同。所有版本都使用路径说明符,它决定了在哪个键中搜索值。它可以是单个键,也可以是键的路径,其中路径元素以特殊字符(.)分隔。(如果没有具体说明)。例如debug.logging.errorlevel 可能是一个带点作为分隔符的有效路径。
1.抛出异常的处理
ptree pt;
/* ... */
float v = pt.get<float>("a.path.to.float.value");
此调用将定位树中的适当节点,并尝试将其数据字符串转换为浮点值。如果失败,则抛出异常。如果路径不存在,它将是ptree_bad_path异常。如果值不能被翻译,它将是ptree_bad_data。它们都源于ptree_error,以使普通处理成为可能。
2.有默认值的版本
ptree pt;
/* ... */
float v = pt.get("a.path.to.float.value", -1.f);
它将执行与上面相同的操作,但是如果失败,它将返回第二个参数指定的默认值(这里-1.f)而不是抛出。这在通常情况下是非常有用的,因为人们想要省略一些键。请注意,在这里通常没有必要的类型规范,因为类型是由默认值参数决定的。
3.可选的版本
ptree pt;
/* ... */
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里有点的路径】:
typedef ptree::path_type path;
pt.get<float>(path("p.a.t.h/t.o/v.a.l.u.e", ‘/‘));
pt.get(path("p.a.t.h/t.o/v.a.l.u.e", ‘/‘), 0, NULL);
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
ptree pt;
pt.put("a.path.to.float.value", 3.14f);
// Overwrites the value
pt.put("a.path.to.float.value", 2.72f);
// Adds a second node with the new value.
pt.add("a.path.to.float.value", 3.14f);
调用put将在指定的路径中插入一个新值,以便调用来指定相同的路径将检索它。
将插入三个新子:
key1,
key1.key2;
key1.key2.key3。
最后一个将接收到一个字符串“3.14”作为数据,而前两个将会有空的数据字符串。总是在现有序列的后面插入新的键
put和add之间的区别是,put将覆盖现有的值,如果有的话,add将创建一个新的节点来保存该值,即使指定的路径引用了现有的节点
与get_value类似,还有一个put_value函数。它不接受路径: