配置文件
对于很多程序中要用的参数如果是可变的,那么最好的处理方式就是通过main函数参数传递,或者从别的地方去获取,这其中之一就是配置文件,但是在一个成熟和架构完善的系统,一般都会做到自动配置,自动部署,所以有的系统里会有一个单独的配置服务存在,每个其它的服务的配置信息从配置中心服务获取,然后运维人员通过操作界面把配置信息下发给配置中心服务,其余服务从配置中心获取变更信息。
共享单车配置文件:
[database]
ip = 127.0.0.1 ;
port = 3306 ;
user = root ;
pwd = 123456 ;
db = qiniubike;
[server]
port = 9090;
ini 的配置文件:[database] 就是我们的俗称的区段,ip,port就是字段,127.0.0.1和3306就是字段的值。
加载配置文件
读取文件内容,然后依照文件内容,把这些字段和值组成key-value
的形式保存在某个数据结构中,这样通过key
(区段+字段)就能找到value
(值)
ini 文件格式:
节
[section]
参数(键=值)
name=value
注解
注解使用分号表示(;)。在分号后面的文字,直到该行结尾都全部为注解。
iniparser 的一条原则是 section 和 key 大小写无关,写入的字符串全部小写化,取出的字符串也全部小写化。
iniparser 下载地址:https://github.com/ndevilla/iniparser
使用方法方法1:
拷贝 src 下的头文件 dictionary.h 和 iniparser.h 到系统目录下,/usr/include 或 /usr/local/include.
拷贝压缩包目录下的静态库 libiniparser.a 和动态库 libiniparser.so.1 到目标文件系统的对应目录下,/usr/lib 或 lib/
使用方法方法2:
直接将 src 下的 dictionary.c,iniparser.c,dictionary.h 和 iniparser.h 到项目目录下,在 makefile 里编译 dictionary.c,iniparser.c,使用时调用头文件就行。
Iniparser库详解
创建配置文件结构体
文件:configdef.h
#include <iostream>
#include "iniconfig.h"
#include <iniparser/iniparser.h>
Iniconfig::Iniconfig():_isloaded(false){
}
Iniconfig::~Iniconfig(){
}
bool Iniconfig::loadfile(const std::string& path){
dictionary* ini = NULL;
if(!_isloaded){
ini = iniparser_load(path.c_str());
if (ini == NULL) {
fprintf(stderr, "cannot parse file: %s\n", path.c_str());
return false ;
}
/*
[database]
ip = 127.0.0.1 ;
port = 3306 ;
user = root ;
pwd = 123456 ;
db = qiniubike;
[server]
port = 9090;
*/
// The third parameter is a candidate parameter
const char* ip = iniparser_getstring(ini, "database:ip","127.0.0.1");
int port = iniparser_getint(ini, "database:port", 3306);
const char* user = iniparser_getstring(ini, "database:user", "root");
const char* pwd = iniparser_getstring(ini, "database:pwd", "123456");
const char* db = iniparser_getstring(ini, "database:db", "dongnaobike");
int sport = iniparser_getint(ini, "server:port", 9090);
_config = st_env_config(std::string(ip), port, std::string(user), \
std::string(pwd), std::string(db), sport);
iniparser_freedict(ini);
_isloaded = true;
}
return _isloaded;
}
const st_env_config& Iniconfig::getconfig(){
return _config;
}
将获取配置信息和初始化配置信息 封装成类
文件:iniconfig.h
#ifndef SHBK_COMMON_INICONFIG_H_
#define SHBK_COMMON_INICONFIG_H_
#include <string>
#include "configdef.h"
class Iniconfig
{
public:
Iniconfig();
~Iniconfig();
bool loadfile(const std::string& path);
const st_env_config& getconfig();
private:
st_env_config _config;
bool _isloaded;
};
#endif // !SHBK_COMMON_INICONFIG_H_
文件:iniconfig.cpp
#include <iostream>
#include "iniconfig.h"
#include <iniparser/iniparser.h>
Iniconfig::Iniconfig():_isloaded(false){
}
Iniconfig::~Iniconfig(){
}
bool Iniconfig::loadfile(const std::string& path){
dictionary* ini = NULL;
if(!_isloaded){
ini = iniparser_load(path.c_str());
if (ini == NULL) {
fprintf(stderr, "cannot parse file: %s\n", path.c_str());
return false ;
}
/*
[database]
ip = 127.0.0.1 ;
port = 3306 ;
user = root ;
pwd = 123456 ;
db = qiniubike;
[server]
port = 9090;
*/
// The third parameter is a candidate parameter
const char* ip = iniparser_getstring(ini, "database:ip","127.0.0.1");
int port = iniparser_getint(ini, "database:port", 3306);
const char* user = iniparser_getstring(ini, "database:user", "root");
const char* pwd = iniparser_getstring(ini, "database:pwd", "123456");
const char* db = iniparser_getstring(ini, "database:db", "dongnaobike");
int sport = iniparser_getint(ini, "server:port", 9090);
_config = st_env_config(std::string(ip), port, std::string(user), \
std::string(pwd), std::string(db), sport);
iniparser_freedict(ini);
_isloaded = true;
}
return _isloaded;
}
const st_env_config& Iniconfig::getconfig(){
return _config;
}
读取配置信息
文件:main.cpp
#include <iostream>
#include "iniconfig.h"
#include "configdef.h"
//shared_bike.exe conf/shared_bike.ini
int main(int argc, char const *argv[]){
if(argc !=2){
std::cout <<"Please input shared_bike <config file path>!"<<std::endl;
return -1;
}
Iniconfig config;
if(!config.loadfile(std::string(argv[1]))){
std::cout <<"Load "<< argv[1] << "failed!" << std::endl;
return -2;
}
st_env_config conf_args = config.getconfig();
std::cout <<"[database] ip: "<<conf_args.db_ip.c_str()<<std::endl;
std::cout <<"[database] port: "<<conf_args.db_port<<std::endl;
std::cout <<"[database] user: "<<conf_args.db_user.c_str()<<std::endl;
std::cout <<"[database] pwd: "<<conf_args.db_pwd.c_str()<<std::endl;
std::cout <<"[server] port: "<<conf_args.svr_port<<std::endl;
return 0;
}
编译
文件:src/common/CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
# 搜集所有在指定路径下的源文件的文件名,将输出结果列表储存在指定的变量中
aux_source_directory(. SOURCE_COMMON_FILES)
# add_ 1 ibrary (<name>[ STATIC | SHARED |MODULE] [ EXCLUDE_FROM_ALL] sourcel [source2...])
# 构建库供他人模块使用
ADD_LIBRARY(common ${SOURCE_COMMON_FILES})
# 用来显式的定义变量
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic -Wall -m64 -pipe -std=c++0x -lrt -Wno-reorder -Wdeprecated-declarations")
# 将指定目录添加到编译器的头文件搜索路径之下
INCLUDE_DIRECTORIES(../../third/include)
# 将指定目录添加到需要链接的库文件目录之下
LINK_DIRECTORIES(../../third/lib/iniparser)
# 该指令的作用为将目标文件与库文件进行链接
TARGET_LINK_LIBRARIES(common iniparser)
TARGET_LINK_LIBRARIES(common dl)
文件:src/CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
# project name
PROJECT(shared_bike)
# 将指定目录添加到编译器的头文件搜索路径之下
INCLUDE_DIRECTORIES(../third/include)
INCLUDE_DIRECTORIES(./common)
# 将指定目录添加到需要链接的库文件目录之下
LINK_DIRECTORIES(../third/lib/iniparser)
LINK_DIRECTORIES(./common)
# 搜集所有在指定路径下的源文件的文件名,将输出结果列表储存在指定的变量中
# 内置变量: CMAKE_SOURCE_DIR 定义了顶级 CMakeLists.txt 所在的文件夹,PROJECT_SOURCE_DIR 定义了包含最近的 project() 命令的 CMakeLists.txt 所在的文件夹
aux_source_directory(${PROJECT_SOURCE_DIR} SOURCE_FILES)
# 使用给定的源文件,为工程引入一个可执行文件
ADD_EXECUTABLE(shared_bike ${SOURCE_FILES})
# 用来显式的定义变量
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic -Wall -m64 -pipe -std=c++0x -lrt -Wno-reorder -Wdeprecated-declarations")
TARGET_LINK_LIBRARIES(shared_bike iniparser)
TARGET_LINK_LIBRARIES(shared_bike common)
# 增加子目录
ADD_SUBDIRECTORY(common)
SET(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR})
INSTALL(TARGETS shared_bike DESTINATION bin)
执行
运行结果: