C++利用boost库加载配置文件参数
- 我们如果要从外部配置文件加载参数,以便提高应用程序的灵活性和可维护性时。
- 通过外部配置文件,程序可以在无需重新编译的情况下轻松地调整配置参数。
如果有config.ini
文件
[database]
host = localhost
port = 3306
user = root
password = rootpassword
[logging]
level = debug
file = log.txt
可以利用两个类来描述这个文件并保存他们的键值对
数据结构的描述
-
SectionInfo
类SectionInfo
类用于存储单个配置节(section)中的键值对(例如存储host、port…),其中键和值均为字符串类型。内部实现了一个std::map<std::string, std::string>
来存储这些键值对。SectionInfo
类主要用于处理配置文件中某个section 的信息,允许通过键来查询对应的值。- 该类支持拷贝构造、赋值运算符重载,确保深拷贝
m_section_data
,同时重载了[]
操作符,方便通过键直接查询对应值。
-
ConfigMgr
类ConfigMgr
类用于管理整个配置文件。它使用std::map<std::string, SectionInfo>
来存储多个 section,每个 section 名称(字符串类型)与SectionInfo
对象相关联。ConfigMgr
是一个管理类,负责处理多个SectionInfo
对象,也就是整个配置文件的结构。通过重载的[]
操作符,用户可以根据 section 名字直接获取对应的SectionInfo
对象,从而进一步访问该 section 内的键值对。
C++实现
- SectionInfo类的实现
struct SectionInfo
{
std::map<std::string, std::string> m_section_data;
SectionInfo(){}
~SectionInfo(){}
SectionInfo(const SectionInfo& rhs)
{
m_section_data = rhs.m_section_data;
}
SectionInfo& operator=(const SectionInfo& rhs)
{
if(&rhs==this) return *this;
this->m_section_data = rhs.m_section_data;
return *this;
}
std::string operator[](const std::string& key)
{
if(m_section_data.find(key)==m_section_data.end())
{
return std::string("");
}
return m_section_data[key];
}
};
- ConfigMgr类的声明
class ConfigMgr {
public:
ConfigMgr();
ConfigMgr(const ConfigMgr& rhs);
~ConfigMgr();
SectionInfo operator[](const std::string& section_name);
ConfigMgr& operator=(const ConfigMgr& rhs);
private:
// 存储section和key-value对的map
std::map<std::string, SectionInfo> m_config_map;
};
- ConfigMgr的定义
// 构造函数:加载并解析配置文件
ConfigMgr::ConfigMgr()
{
// 获取当前路径, 当前路径为可执行程序所在路径
boost::filesystem::path current_path = boost::filesystem::current_path();
// 构建config.ini文件的完整路径
boost::filesystem::path config_path = current_path / "config.ini";
std::cout << "Config path: " << config_path << std::endl;
// 使用Boost.PropertyTree来读取INI文件
boost::property_tree::ptree pt;
boost::property_tree::read_ini(config_path.string(), pt); // 读取INI文件并存储在ptree中
// 遍历INI文件中的所有section
for (const auto& section_pair : pt) {
const std::string& section_name = section_pair.first; // 获取section名称
const boost::property_tree::ptree& section_tree = section_pair.second; // 获取该section的树结构
// 存储每个section的键值对
std::map<std::string, std::string> section_config;
// 遍历section中的所有key-value对
for (const auto& key_value_pair : section_tree) {
const std::string& key = key_value_pair.first; // 获取键名
const std::string& value = key_value_pair.second.get_value<std::string>(); // 获取键对应的值
section_config[key] = value; // 将键值对存入section_config
}
// 将该section的键值对存入SectionInfo对象中
SectionInfo sectionInfo;
sectionInfo.m_section_data = section_config;
// 将SectionInfo对象保存到配置映射中,键为section名称
m_config_map[section_name] = sectionInfo;
}
// 输出所有的section及其包含的键值对,便于检查
for (const auto& section_entry : m_config_map) {
const std::string& section_name = section_entry.first; // 获取section名称
SectionInfo section_config = section_entry.second; // 获取SectionInfo对象
std::cout << "[" << section_name << "]" << std::endl; // 输出section名称
for (const auto& key_value_pair : section_config.m_section_data) {
std::cout << key_value_pair.first << "=" << key_value_pair.second << std::endl;
}
}
}
ConfigMgr::ConfigMgr(const ConfigMgr& rhs)
{
m_config_map = rhs.m_config_map;
}
ConfigMgr::~ConfigMgr()
{
}
SectionInfo ConfigMgr::operator[](const std::string& section_name)
{
if(m_config_map.find(section_name) == m_config_map.end())
{
return SectionInfo();
}
return m_config_map[section_name];
}
ConfigMgr& ConfigMgr::operator=(const ConfigMgr& rhs)
{
if(&rhs == this) return *this;
this->m_config_map = rhs.m_config_map;
return *this;
}
- 在main函数中
#include "ConfigMgr.h"
int main()
{
ConfigMgr config;
std::cout << "----------- main test -----------" << std::endl;
std::cout <<"host:" << config["database"]["host"] << std::endl;
std::cout <<"file" << config["logging"]["file"] << std::endl;
return 0;
}
- 输出结果,正确