在一般项目中经常会用到配置文件配置一些系统参数,比如网关的端口号、memcache、redis等配置参数,数据库的ip地址、端口号、用户名密码等。 在JAVA中有properties文件读取类。 c++中有ini的读取实现,注册表的读取实现,普通文件读取等实现, 我们项目中使用的类似ini配置文件,支持分区配置参数。
配置文件如下:
代码实现如下:
configure.h
#ifndef GW_CONFIGURE_H_
#define GW_CONFIGURE_H_#include <string>
#include <map>
#include <stdint.h>#include "base/basic_types.h"
namespace gateway {class Configure { public: Configure(); ~Configure(); int Init(const std::string& file);
std::string GetValueAsString(const std::string& group,
const std::string& key,
const std::string& default_value) const;
uint32_t GetValueAsUint32(const std::string& group,
const std::string& key,
uint32_t default_value) const;
double GetValueAsDouble(const std::string& group,
const std::string& key,
double default_value) const;
bool GetValueAsBool(const std::string& group,
const std::string& key,
bool default_value) const;
private: private: std::map<std::string, std::map<std::string, std::string> > items_;
DISALLOW_COPY_AND_ASSIGN(Configure);};} // namespace gateway
#endif // GW_CONFIGURE_H_
configure.h代码
configure.cpp代码如下:
#include <stdio.h>
#include <stdlib.h>#include <IOStream>#include "gateway/configure.h"
namespace gateway {class ConfigFile {public: ConfigFile(); ~ConfigFile(); int Init(const char* file);
int ParseFile(std::map<std::string, std::map<std::string, std::string> >& group_items);private: int GetLine(std::string& line); int GetKeyAndValue(const std::string& line, std::string& key, std::string& value);
void Trim(std::string& str);
private: FILE* pf_; enum {
kErrorRow = 0,
kEmptyRow, kGroupRow, kValueRow, }; DISALLOW_COPY_AND_ASSIGN(ConfigFile);};ConfigFile::ConfigFile() : pf_(NULL) {}ConfigFile::~ConfigFile() { if (pf_ != NULL) {
fclose(pf_); }}int ConfigFile::Init(const char* file) {
pf_ = fopen(file, "r");
if (pf_ == NULL) return RESULT_ERROR;
return RESULT_OK;
}void ConfigFile::Trim(std::string& str) {
size_t size = str.size();
if (size == 0) return ;
size_t begin = 0;
while (begin < size && str[begin] == ' ') begin++;
size_t end = size - 1;
while (end > begin && str[end] == ' ') end--;
if (end >= begin) {
str = str.substr(begin, end + 1 - begin);
} else {
str = "";
}}int ConfigFile::GetLine(std::string& line) { const int kLen = 512;
char buf[kLen] = {0};
if (fgets(buf, kLen, pf_) != NULL) {
line = buf; Trim(line); if (line.length() < 2) return kEmptyRow;
if (line[0] == '#') return kEmptyRow;
std::string s = line.substr(line.length() - 2);
if (s == "nr") {
line = line.substr(0, line.length() - 2);
} s = line.substr(line.length() - 1);
if (s == "r" || s == "n") {
line = line.substr(0, line.length() - 1);
} if (line.length() == 0) return kEmptyRow;
if ((line[0] == '[') && (line[line.length() - 1] == ']')) {
line = line.substr(1, line.length() - 2);
return kGroupRow;
} return kValueRow;
} //包括
return kErrorRow;
}
int ConfigFile::GetKeyAndValue(const std::string& line, std::string& key, std::string& value) {
int pos = line.find_first_of("=");
if (pos < 0) return RESULT_ERROR;
key = line.substr(0, pos);
Trim(key);
value = line.substr(pos + 1);
Trim(value);
return RESULT_OK;
}
int ConfigFile::ParseFile(std::map<std::string, std::map<std::string, std::string> >& group_items) {
fseek(pf_, 0, SEEK_SET);
int type = kErrorRow;
std::string line;
std::string group;
std::string key;
std::string value;
while ((type = GetLine(line)) != kErrorRow) {
//处理行
if (type == kGroupRow) {
group = line;
group_items[group] = std::map<std::string, std::string>();
} else if (type == kValueRow){
//找到key and value
if (GetKeyAndValue(line, key, value) == RESULT_OK) {
group_items[group][key] = value;
}
}
}
return RESULT_OK;
}
//=============================
Configure::Configure() {
}
Configure::~Configure() {
}
int Configure::Init(const std::string& file) {
ConfigFile config;
int result = config.Init(file.c_str());
if (result != RESULT_OK) return result;
//解析具体配置文件:
result = config.ParseFile(items_);
return result;
}
std::string Configure::GetValueAsString(const std::string& group,
const std::string& key,
const std::string& default_value) const {
std::string result = default_value;
std::map<std::string, std::map<std::string, std::string> >::const_iterator g_it = items_.find(group);
if (g_it != items_.end()) {
std::map<std::string, std::string>::const_iterator it = g_it->second.find(key);
if (it != g_it->second.end()) {
result = it->second;
}
}
return result;
}
uint32_t Configure::GetValueAsUint32(const std::string& group,
const std::string& key,
uint32_t default_value) const {
uint32_t result = default_value;
std::map<std::string, std::map<std::string, std::string> >::const_iterator g_it = items_.find(group);
if (g_it != items_.end()) {
std::map<std::string, std::string>::const_iterator it = g_it->second.find(key);
if (it != g_it->second.end()) {
result = atoi(it->second.c_str());
}
}
return result;
}
double Configure::GetValueAsDouble(const std::string& group,
const std::string& key,
double default_value) const {
double result = default_value;
std::map<std::string, std::map<std::string, std::string> >::const_iterator g_it = items_.find(group);
if (g_it != items_.end()) {
std::map<std::string, std::string>::const_iterator it = g_it->second.find(key);
if (it != g_it->second.end()) {
result = atof(it->second.c_str());
}
}
return result;
}
bool Configure::GetValueAsBool(const std::string& group,
const std::string& key,
bool default_value) const {
bool result = default_value;
std::map<std::string, std::map<std::string, std::string> >::const_iterator g_it = items_.find(group);
if (g_it != items_.end()) {
std::map<std::string, std::string>::const_iterator it = g_it->second.find(key);
if (it != g_it->second.end()) {
result = (it->second == "1");
}
}
return result;
}
} // namespace gateway
使用样例如下:
int gw_set_opt(gateway::Gateway::Options& options, const std::string& file) {
gateway::Configure config;
if (config.Init(file) != RESULT_OK) {
return RESULT_ERROR;
} options.unit_io_nevents = config.GetValueAsUint32("unit", "io_nevents", options.unit_io_nevents);
options.unit_reactor_timeout = config.GetValueAsUint32("unit", "reactor_timeout", options.unit_reactor_timeout);
options.unit_timer_nevents = 0;
options.unit_conn_timeout = config.GetValueAsUint32("unit", "conn_timeout", options.unit_conn_timeout);
options.unit_listen_addr = config.GetValueAsString("unit", "listen_addr", options.unit_listen_addr);