C++ Boost PropertyTree示例超详细讲解

目录
  • 一、提要
  • 二、应用示例
  • 练习

一、提要

借助类 boost::property_tree::ptree,Boost.PropertyTree 提供了一个树结构来存储键/值对。树形结构意味着一个树干存在许多分支,其中有许多树枝。文件系统是树结构的一个很好的例子。文件系统有一个带有子目录的根目录,这些子目录本身可以有子目录等等。

二、应用示例

要使用 boost::property_tree::ptree,请包含头文件 boost/property_tree/ptree.hpp。这是一个主头文件,因此 Boost.PropertyTree 不需要包含其他头文件。

示例 25.1。访问 boost::property_tree::ptree 中的数据

#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

example25.1 使用 boost::property_tree::ptree 来存储目录的路径。这是通过调用 put() 来完成的。此成员函数需要两个参数,因为 boost::property_tree::ptree 是一个保存键/值对的树结构。树不仅由树枝和树枝组成,还必须为每个树枝和树枝分配一个值。在示例 25.1 中,该值为“20 个文件”。

传递给 put() 的第一个参数更有趣。它是一个目录的路径。但是,它不使用反斜杠,这是 Windows 上常见的路径分隔符。它使用点。

您需要使用点,因为它是 Boost.PropertyTree 期望的键的分隔符。参数“C:.Windows.System”告诉 pt 创建一个名为 C: 的分支,其中一个名为 Windows 的分支具有另一个名为 System 的分支。点创建分支的嵌套结构。如果“C:\Windows\System”作为参数传递,pt 将只有一个名为 C:\Windows\System 的分支。

调用 put() 后,访问 pt 以读取存储的值“20 个文件”并将其写入标准输出。这是通过从一个分支跳转到另一个分支 - 或从一个目录跳转到另一个目录来完成的。

要访问子分支,您可以调用 get_child(),它会返回对与调用 get_child() 相同类型的对象的引用。在示例 25.1 中,这是对 boost::property_tree::ptree 的引用。因为每个分支都可以有子分支,并且由于高低分支之间没有结构差异,所以使用相同的类型。

第三次调用 get_child() 检索 boost::property_tree::ptree,它表示目录 System。调用 get_value() 以读取在示例开头使用 put() 存储的值。

请注意,get_value() 是一个函数模板。您将返回值的类型作为模板参数传递。这样 get_value() 可以进行自动类型转换。

示例 25.2。访问 basic_ptree<std::string, int> 中的数据

#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 有两个变化。这些更改是为了更轻松地保存目录路径和目录中的文件数量。首先,路径在传递给 put() 时使用反斜杠作为分隔符。其次,文件的数量存储为 int。

默认情况下,Boost.PropertyTree 使用点作为键的分隔符。如果您需要使用其他字符(例如反斜杠)作为分隔符,则不要将键作为字符串传递给 put()。相反,您将其包装在 boost::property_tree::ptree::path_type 类型的对象中。这个类的构造函数依赖于 boost::property_tree::ptree,它的第一个参数是键,第二个参数是分隔符。这样,您可以使用 C:\Windows\System 等路径,如示例 25.2 所示,而无需将反斜杠替换为点。

boost::property_tree::ptree 基于类模板 boost::property_tree::basic_ptree。因为键和值通常是字符串,所以 boost::property_tree::ptree 是预定义的。但是,您可以将 boost::property_tree::basic_ptree 用于键和值的不同类型。示例 25.2 中的树使用 int 来存储目录中的文件数,而不是字符串。

boost::property_tree::ptree 提供成员函数 begin() 和 end()。但是,boost::property_tree::ptree 只允许您在一个级别上迭代分支。示例 25.2 遍历 C:\Windows 的子目录。您无法让迭代器遍历所有级别的所有分支。

示例 25.2 中的 for 循环读取 C:\Windows 的所有子目录中的文件数以计算总数。因此,该示例显示 70。该示例不直接访问 ptree 类型的对象。相反,它迭代类型为 std::pair<std::string, ptree> 的元素。 first 包含当前分支的键。即示例 25.2 中的系统和游标。第二个提供对 ptree 类型对象的访问,它表示可能的子目录。在示例中,仅读取分配给 System 和 Cursors 的值。如示例 25.1,调用成员函数 get_value()。

boost::property_tree::ptree 只存储当前分支的值,而不是它的键。您可以使用 get_value() 获取值,但没有获取密钥的成员函数。密钥存储在 boost::property_tree::ptree 上一级。这也解释了为什么 for 循环会迭代 std::pair<std::string, ptree> 类型的元素。

示例 25.3。使用翻译器访问数据

#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';
}

Example25.3

示例 25.3 与 boost::property_tree::iptree 一起使用来自 Boost.PropertyTree 的另一个预定义树。通常,此类型的行为类似于 boost::property_tree::ptree。唯一的区别是 boost::property_tree::iptree 不区分大小写。例如,使用 C:\Windows\System 键存储的值可以用 c:\windows\system 读取。

与示例 25.1 不同,get_child() 不会被多次调用来访问子分支。正如 put() 可用于将值直接存储在子分支中一样,子分支中的值也可以使用 get() 读取。键的定义方式相同——例如使用 boost::property_tree::iptree::path_type。

与 get_value() 一样,get() 是一个函数模板。您必须将返回值的类型作为模板参数传递。 Boost.PropertyTree 进行自动类型转换。

为了转换类型,Boost.PropertyTree 使用翻译器。该库提供了一些开箱即用的翻译器,它们基于流并且可以自动转换类型。

示例 25.3 与 boost::property_tree::iptree 一起使用来自 Boost.PropertyTree 的另一个预定义树。通常,此类型的行为类似于 boost::property_tree::ptree。唯一的区别是 boost::property_tree::iptree 不区分大小写。例如,使用 C:\Windows\System 键存储的值可以用 c:\windows\system 读取。

与示例 25.1 不同,get_child() 不会被多次调用来访问子分支。正如 put() 可用于将值直接存储在子分支中一样,子分支中的值也可以使用 get() 读取。键的定义方式相同——例如使用 boost::property_tree::iptree::path_type。

与 get_value() 一样,get() 是一个函数模板。您必须将返回值的类型作为模板参数传递。 Boost.PropertyTree 进行自动类型转换。

为了转换类型,Boost.PropertyTree 使用翻译器。该库提供了一些开箱即用的翻译器,它们基于流并且可以自动转换类型。

Example25.3

#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 定义了转换器 string_to_int_translator,它将 std::string 类型的值转换为 int。翻译器作为附加参数传递给 get()。因为翻译器只是用来阅读的,所以它只定义了一个成员函数,get_value()。如果您也想使用翻译器进行写作,那么您需要定义一个成员函数 put_value(),然后将翻译器作为附加参数传递给 put()。

get_value() 返回 pt 中使用的类型的值。但是,由于类型转换并不总是成功,因此使用了 boost::optional。如果示例 25.3 中存储的值无法使用 std::strtol() 转换为 int,则将返回 boost::optional 类型的空对象。

请注意,翻译人员还必须定义 internal_type 和 external_type 两种类型。如果需要在存储数据时进行类型转换,请定义类似于 get_value() 的 put_value()。

如果您修改示例 25.3 以存储值“20”而不是值“20 个文件”,则可以调用 get_value() 而无需传递翻译器。 Boost.PropertyTree 提供的翻译器可以将 std::string 转换为 int。但是,只有在可以转换整个字符串时,类型转换才会成功。字符串不能包含任何字母。因为只要字符串以数字开头,std::strtol() 就可以进行类型转换,因此示例 25.3 中使用了更自由的转换器 string_to_int_translator。

示例 25.4。 boost::property_tree::ptree 的各种成员函数

如果要读取键的值,可以调用成员函数 get_optional(),但不确定该键是否存在。 get_optional() 返回 boost::optional 类型对象中的值。如果未找到密钥,则该对象为空。否则,get_optional() 的工作方式与 get() 相同。

看起来 put_child() 和 add_child() 与 put() 相同。不同之处在于 put() 只创建一个键/值对,而 put_child() 和 add_child() 插入整个子树。请注意,类型为 boost::property_tree::ptree 的对象作为第二个参数传递给 put_child() 和 add_child()。

put_child() 和 add_child() 之间的区别在于 put_child() 会在该键已经存在时访问该键,而 add_child() 总是将一个新键插入到树中。这就是示例 25.4 中的树有两个名为“D:.Program Files”的键的原因。根据用例,这可能会令人困惑。如果一棵树代表一个文件系统,则不应有两条相同的路径。如果您不想在树中重复,则必须避免插入相同的键。

示例 25.4 显示了 for 循环中“D:”下方键的值。该示例将 50 个文件和 60 个文件写入标准输出,这证明有两个相同的键,称为“D:.Program Files”。

示例 25.4 中引入的最后一个成员函数是 get_child_optional()。此函数的使用方式与 get_child() 类似。 get_child_optional() 返回 boost::optional 类型的对象。如果您不确定密钥是否存在,则调用 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 不仅仅提供结构来管理内存中的数据。从示例 25.5 中可以看出,该库还提供了将 boost::property_tree::ptree 保存在文件中并从文件中加载的函数。

头文件 boost/property_tree/json_parser.hpp 提供对函数 boost::property_tree::json_parser::write_json() 和 boost::property_tree::json_parser::read_json() 的访问。这些函数可以保存和加载以 JSON 格式序列化的 boost::property_tree::ptree。这样您就可以支持 JSON 格式的配置文件。

如果要调用将 boost::property_tree::ptree 存储在文件中或从文件中加载的函数,则必须包含头文件,例如 boost/property_tree/json_parser.hpp。仅包含 boost/property_tree/ptree.hpp 是不够的。

除了函数 boost::property_tree::json_parser::write_json() 和 boost::property_tree::json_parser::read_json() 之外,Boost.PropertyTree 还提供了其他数据格式的函数。您使用来自 boost/property_tree/ini_parser.hpp 的 boost::property_tree::ini_parser::write_ini() 和 boost::property_tree::ini_parser::read_ini() 来支持 INI 文件。使用来自 boost/property_tree/xml_parser.hpp 的 boost::property_tree::xml_parser::write_xml() 和 boost::property_tree::xml_parser::read_xml(),可以以 XML 格式加载和存储数据。使用来自 boost/property_tree/info_parser.hpp 的 boost::property_tree::info_parser::write_info() 和 boost::property_tree::info_parser::read_info(),您可以访问另一种为序列化 Boost 中的树而开发和优化的格式.PropertyTree。

任何受支持的格式都不能保证 boost::property_tree::ptree 在保存和重新加载后看起来是一样的。例如,JSON 格式可能会丢失类型信息,因为 boost::property_tree::ptree 无法区分 true 和“true”。类型始终相同。即使各种函数可以轻松保存和加载 boost::property_tree::ptree,但不要忘记 Boost.PropertyTree 并不完全支持这些格式。该库的主要重点是结构 boost::property_tree::ptree,而不是支持各种数据格式。

练习

创建一个加载此 JSON 文件并将所有动物的名称写入标准输出的程序。如果“all”设置为 true,则程序不仅应将所有动物的名称,而且应将所有属性写入标准输出:

{
  "animals": [
    {
      "name": "cat",
      "legs": 4,
      "has_tail": true
    },
    {
      "name": "spider",
      "legs": 8,
      "has_tail": false
    }
  ],
  "log": {
    "all": true
  }
}

到此这篇关于C++ Boost PropertyTree示例超详细讲解的文章就介绍到这了,更多相关C++ Boost PropertyTree内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++ Boost Any示例分析使用

    目录 一.提要 二.Boost.Any示例 一.提要 强类型语言,例如 C++,要求每个变量都有一个特定的类型来定义它可以存储什么样的信息.其他语言,例如 JavaScript,允许开发人员将任何类型的信息存储在变量中.例如,在 JavaScript 中,单个变量可以包含一个字符串,然后是一个数字,然后是一个布尔值. 二.Boost.Any示例 Boost.Any 提供了 boost::any 类,它与 JavaScript 变量一样,可以存储任意类型的信息. 示例 23.1.使用 boost:

  • C++ Boost Optional示例超详细讲解

    目录 一.概述 二.Boost.Optional 一.概述 数据结构类似于容器,因为它们可以存储一个或多个元素.但是,它们与容器不同,因为它们不支持容器通常支持的操作.例如,使用本部分介绍的数据结构,不可能在一次迭代中访问所有元素. Boost.Optional 可以很容易地标记可选的返回值.使用 Boost.Optional 创建的对象要么是空的,要么包含单个元素.使用 Boost.Optional,您无需使用空指针或 -1 等特殊值来指示函数可能没有返回值. Boost.Tuple 提供了

  • C++ Boost Tokenizer使用详细讲解

    目录 介绍 示例一 示例二 示例三 示例四 示例五 示例六 示例七 介绍 库 Boost.Tokenizer 允许您通过将某些字符解释为分隔符来迭代字符串中的部分表达式.使用 boost::tokenizer 迭代字符串中的部分表达式 示例一 使用 boost::tokenizer 迭代字符串中的部分表达式 #include <boost/tokenizer.hpp> #include <string> #include <iostream> int main() {

  • C++ Boost Variant示例超详细讲解

    目录 一.提要 二.示例 一.提要 Boost.Variant 提供了一个类似于 union 的名为 boost::variant 的类.您可以将不同类型的值存储在 boost::variant 变量中.在任何时候只能存储一个值.分配新值时,旧值将被覆盖.但是,新值的类型可能与旧值不同.唯一的要求是这些类型必须作为模板参数传递给 boost::variant,这样它们才能为 boost::variant 变量所知. boost::variant 支持任何类型.例如,可以将 std::string

  • C++ Boost MultiIndex使用详细介绍

    目录 一.关于BOOST的容器 二.Boost.MultiIndex 练习 一.关于BOOST的容器 容器是 C++ 中最有用的数据结构之一.标准库提供了许多容器,而 Boost 库提供的更多. Boost.MultiIndex 更进一步:这个库中的容器可以同时支持来自其他容器的多个接口.来自 Boost.MultiIndex 的容器就像合并的容器,并提供了与它们合并的所有容器的优点. Boost.Bimap 基于 Boost.MultiIndex.它提供了一个类似于 std::unordere

  • C++ Boost Bimap示例详细讲解

    目录 一.提要 二.示例 练习 一.提要 库 Boost.Bimap 基于 Boost.MultiIndex 并提供了一个无需先定义即可立即使用的容器.该容器类似于 std::map,但支持从任一侧查找值. Boost.Bimap 允许您根据访问地图的方式创建任意一侧都可以作为关键点的地图.当您访问左侧作为键时,右侧是值,反之亦然. 二.示例 Example13.1.Usingboost::bimap #include <boost/bimap.hpp> #include <string

  • C++ Boost PropertyTree示例超详细讲解

    目录 一.提要 二.应用示例 练习 一.提要 借助类 boost::property_tree::ptree,Boost.PropertyTree 提供了一个树结构来存储键/值对.树形结构意味着一个树干存在许多分支,其中有许多树枝.文件系统是树结构的一个很好的例子.文件系统有一个带有子目录的根目录,这些子目录本身可以有子目录等等. 二.应用示例 要使用 boost::property_tree::ptree,请包含头文件 boost/property_tree/ptree.hpp.这是一个主头文

  • C++ Boost Lockfree超详细讲解使用方法

    目录 一.说明 二.示例和代码 Boost.Lockfree 一.说明 Boost.Lockfree 提供线程安全和无锁容器.可以从多个线程访问此库中的容器,而无需同步访问. 在 1.56.0 版本中,Boost.Lockfree 只提供了两个容器:boost::lockfree::queue 类型的队列和 boost::lockfree::stack 类型的栈.对于队列,可以使用第二个实现:boost::lockfree::spsc_queue.此类针对只有一个线程写入队列和只有一个线程从队列

  • C++ Boost weak_ptr智能指针超详细讲解

    目录 一.提要 二.特别智能指针(Special Smart Pointers) 一.提要 在 C++11 中,boost::weak_ptr是另一类智能指针,一般是用COM组件生成.调用,本文阐述这种指针的特点和用法. 二.特别智能指针(Special Smart Pointers) 到目前为止介绍的每个智能指针都可以在不同的场景中单独使用.但是,boost::weak_ptr 仅在与 boost::shared_ptr 结合使用时才有意义. boost::weak_ptr 在 boost/w

  • C++ Boost ScopeExit超详细讲解

    目录 一.提要 二.退出作用域(Boost.ScopeExit) 2.1 范例1.UsingBOOST_SCOPE_EXIT 2.2 示例2.Boost.ScopeExit和C++11的lambda函数 2.3 示例3.特点BOOST_SCOPE_EXIT 三.练习 一.提要 资源有很多种,每种都封装一套,还是挺繁琐的!对于比较少使用或者一个程序很可能只会用一次的资源,我们不想封装,在这种情况下用Boost.ScopeExit. 二.退出作用域(Boost.ScopeExit) 库 Boost.

  • C++ Boost System超详细讲解

    目录 一.说明 二.关于 Boost.System库 一.说明 以下库支持错误处理. Boost.System 提供类来描述和识别错误.自 C++11 以来,这些类已成为标准库的一部分. Boost.Exception 使得在抛出异常后附加数据成为可能. 二.关于 Boost.System库 Boost.System Boost.System 是一个库,本质上定义了四个类来识别错误.所有四个类都已添加到 C++11 的标准库中.如果您的开发环境支持 C++11,则无需使用 Boost.Syste

  • C++ Boost Uuid超详细讲解

    目录 一.说明 二.Boost.Uuid库示例和代码 一.说明 Boost.Uuid 为 UUID 提供生成器. UUID 是不依赖于中央协调实例的通用唯一标识符.例如,没有数据库存储所有生成的 UUID,可以检查这些 UUID 是否使用了新的 UUID. UUID 由必须唯一标识组件的分布式系统使用.例如,Microsoft 使用 UUID 来识别 COM 世界中的接口.对于为 COM 开发的新接口,可以轻松分配唯一标识符. UUID 是 128 位数字.存在多种生成 UUID 的方法.例如,

  • C++ Boost Archive超详细讲解

    目录 一.说明 二.关于Archive库 一.说明 对Boost.Serialization库的应用,存在如下内容: Archive Pointers and References Serialization of Class Hierarchy Objects Wrapper Functions for Optimization Boost.Serialization 库可以将 C++ 程序中的对象转换为可以保存和加载以恢复对象的字节序列.有不同的数据格式可用于定义生成字节序列的规则. Boo

  • C++ Boost ProgramOptions超详细讲解

    目录 一.说明 二.示例Boost.ProgramOptions 一.说明 Boost.ProgramOptions Boost.ProgramOptions 是一个可以轻松解析命令行选项的库,例如,控制台应用程序.如果您使用图形用户界面开发应用程序,命令行选项通常并不重要. 要使用 Boost.ProgramOptions 解析命令行选项,需要以下三个步骤: 定义命令行选项.您给它们命名并指定哪些可以设置为一个值.如果命令行选项被解析为键/值对,您还可以设置值的类型——例如,它是字符串还是数字

随机推荐