要将原来程序里面的配置文件模块从c迁移到c++, 虽然自己也尝试写了个,但为了更好的跨平台性,还是决定使用boost库中的program option。
简单提一下安装和编译:
1.下载boost的源码包
2.
./bootstrap.sh
sudo ./b2 install
3. 如果提示没有patchlevel.h
sudo apt-get install python-dev
4. 如果提示没有bzlib.h
sudo apt-get install libbz2-dev
5. 编译命令如下:
g++ -o first first.cpp -I /usr/local/include/boost -L /usr/local/lib/ -lboos t_program_options
注意为了更好的跨平台, 把-I 和 -L放在 -o first first.cpp 的后面。
然后进入正题,如何用boost 的program option(下文所写为PO)库读未知section的配置文件。
boost的PO在解析配置文件前需要先定义配置文件的描述options_description,例如
options_description config("Configuration");
config.add_options()
("section1.key2", value< vector >()->notifier( range_notify ), "Ranges for partition");
boost本身支持section和重名key。 例如:
[section1]
key1=v1
key2=v2
key2=v22
其实boost的PO把它看作
section1.key1=v1
section1.key2=v2 v22 (key2的值类型是一个数组)
对于未知section的配置文件,我们需要在另一个配置文件中描述它。
例如
conf1:
sections=section1
sections=section2
conf2:
[section1]
key1=v1
[section2]
key1=v1
然后先读conf1,根据读到的sections的内容动态的去生成conf2的配置文件描述,然后在读conf2.
示例的配置文件如下:
proxy.conf:
# range config
partition_range = 1
partition_range = 2
partition_range = 3
# backend server config
rwserver = s-2-8
rdserver = a-2-9
rdserver = b-2-9
# config for detail config file
detail_conf = proxy_detail.conf
schemas=schema1
schemas=schema2
proxy_detail.conf:
[schema1]
name = s1
[schema2]
name = s2
示例代码如下:
options_description only_config("Only Configuration");
only_config.add_options()
("partition_range", value< vector >()->notifier( range_notify ), "Ranges for partition")
("rwserver", value()->required(), "RW server")
("rdserver", value< vector >(), "RD server")
("schemas", value< vector >(), "Name and num of schemas")
("detail_conf", value()->default_value("proxy_detail.conf"),
"More detail and business related configuration file.")
;
ifstream ifs(config_file.c_str());
if (!ifs)
{
cout << "can not open config file: " << config_file << "\n";
return 0;
}
else
{
store(parse_config_file(ifs, only_config), vm);
notify(vm);
vector schemas = vm["schemas"].as< vector >();
options_description detail_config("Detail conf");
for (i = 0; i < schemas.size(); i++)
{
string tmp = schemas[i] + ".name";
const char *name = const_cast(tmp.c_str());
detail_config.add_options()
(name, value(), "Name of schema")
;
}
ifs.close();
schema_config_file = vm["detail_conf"].as< string >();
ifstream ifs2(schema_config_file.c_str());
if (!ifs2)
{
cout << "can not open detail config file: " << schema_config_file << "\n";
return 0;
}
store(parse_config_file(ifs2, detail_config), vm);
notify(vm);
ifs2.close();
}