Boost.PropertyTree 五分钟快速入门
本教程使用XML。注意,这个库不是专门绑定到XML的,而是可以使用任何其他支持的格式(如INI或JSON)。之所以选择XML,是因为作者认为很多人都熟悉XML。
假设我们正在为某个应用程序编写一个日志系统,并且需要在程序启动时从文件中读取日志配置。带有日志配置的文件如下所示:
<debug>
<filename>debug.log</filename>
<modules>
<module>Finance</module>
<module>Admin</module>
<module>HR</module>
</modules>
<level>2</level>
</debug>
它包含日志文件名、启用日志记录的模块列表和调试级别值。
我们需要包含的头文件:
#include<boost/property_tree/ptree.hpp>
#include<boost/property_tree/xml_parser.hpp>
#include<boost/foreach.hpp>
#include<string>
#include<set>
#include<exception>
#include<iostream>
namespace pt = boost::property_tree;
为了存储日志的配置信息,我们创建一个结构来存储它
struct debug_settings
{
std::string m_file;// log filename
int m_level;// debug level
std::set<std::string> m_modules;// modules where logging is enabled
void load(const std::string &filename);
void save(const std::string &filename);
};
现在需要做的就是编写load()和save()成员函数的实现。让我们先来处理load()。它只包含7行代码,尽管它做了所有必要的事情,包括错误报告:
void debug_settings::load(const std::string &filename)
{
// Create empty property tree object
pt::ptree tree;
// Parse the XML into the property tree.
pt::read_xml(filename, tree);
// Use the throwing version of get to find the debug filename.
// If the path cannot be resolved, an exception is thrown.
m_file = tree.get<std::string>("debug.filename");
// Use the default-value version of get to find the debug level.
// Note that the default value is used to deduce the target type.
m_level = tree.get("debug.level",0);
// Use get_child to find the node containing the modules, and iterate over
// its children. If the path cannot be resolved, get_child throws.
// A C++11 for-range loop would also work.
BOOST_FOREACH(pt::ptree::value_type &v, tree.get_child("debug.modules")){
// The data function is used to access the data stored in a node.
m_modules.insert(v.second.data());
}
}
存储函数
void debug_settings::save(const std::string &filename)
{
// Create an empty property tree object.
pt::ptree tree;
// Put the simple values into the tree. The integer is automatically
// converted to a string. Note that the "debug" node is automatically
// created if it doesn't exist.
tree.put("debug.filename", m_file);
tree.put("debug.level", m_level);
// Add all the modules. Unlike put, which overwrites existing nodes, add
// adds a new node at the lowest level, so the "modules" node will have
// multiple "module" children.
BOOST_FOREACH(const std::string &name, m_modules)
tree.add("debug.modules.module", name);
// Write property tree to XML file
pt::write_xml(filename, tree);
}
来个全代码的:
//
// Created by 瓜不甜 on 2018/1/20.
//
#include<boost/property_tree/ptree.hpp>
#include<boost/property_tree/xml_parser.hpp>
#include<boost/foreach.hpp>
#include<string>
#include<set>
#include<exception>
#include<iostream>
namespace pt = boost::property_tree;
struct debug_settings
{
std::string m_file;// log filename
int m_level;// debug level
std::set<std::string> m_modules;// modules where logging is enabled
void load(const std::string &filename);
void save(const std::string &filename);
};
void debug_settings::load(const std::string &filename)
{
// Create empty property tree object
pt::ptree tree;
// Parse the XML into the property tree.
pt::read_xml(filename, tree);
// Use the throwing version of get to find the debug filename.
// If the path cannot be resolved, an exception is thrown.
m_file = tree.get<std::string>("debug.filename");
// Use the default-value version of get to find the debug level.
// Note that the default value is used to deduce the target type.
m_level = tree.get("debug.level",0);
// Use get_child to find the node containing the modules, and iterate over
// its children. If the path cannot be resolved, get_child throws.
// A C++11 for-range loop would also work.
BOOST_FOREACH(pt::ptree::value_type &v, tree.get_child("debug.modules")){
// The data function is used to access the data stored in a node.
m_modules.insert(v.second.data());
}
}
void debug_settings::save(const std::string &filename)
{
// Create an empty property tree object.
pt::ptree tree;
// Put the simple values into the tree. The integer is automatically
// converted to a string. Note that the "debug" node is automatically
// created if it doesn't exist.
tree.put("debug.filename", m_file);
tree.put("debug.level", m_level);
// Add all the modules. Unlike put, which overwrites existing nodes, add
// adds a new node at the lowest level, so the "modules" node will have
// multiple "module" children.
BOOST_FOREACH(const std::string &name, m_modules)
tree.add("debug.modules.module", name);
// Write property tree to XML file
pt::write_xml(filename, tree);
}
void test1(){
debug_settings a;
a.load("setting.xml");
std::cout<<a.m_file<<std::endl;
std::cout<<a.m_level<<std::endl;
std::set<std::string>::iterator i;
for( i = a.m_modules.begin(); i != a.m_modules.end();++i){
std::cout<<*i<<std::endl;
}
}
很明显,这个是个非常好用的结构!
简单,高效!
这里有个foreach结构:
BOOST_FOREACH(const std::string &name, m_modules)
{
tree.add("debug.modules.module", name);
}
这个是C++的一个类宏的高级应用了