> 文章列表 > 工程化项目配置【iniparser的安装与使用】

工程化项目配置【iniparser的安装与使用】

工程化项目配置【iniparser的安装与使用】

文章目录

  • 前言
  • iniparser的安装
  • ini文件通过iniparser进行解析
    • 代码展示
    • iniparser解析数据的流程
    • cmake设计
  • 结语

前言

对于很多程序中要用的参数如果是可变的,那么最好的处理方式就是通过main函数参数传递【就是我们经常见到的int main (int argc,char *argv[]){…}中的argc以及argv】,或者从别的地方去获取,这其中之一就是配置文件,但是在一个成熟和架构完善的系统,一般都会做到自动配置,自动部署,所以有的系统里会有一个单独的配置服务存在,每个其它的服务的配置信息从配置中心服务获取,然后运维人员通过操作界面把配置信息下发给配置中心服务,其余服务从配置中心获取变更信息。
几乎每一个大型互联网项目都会涉及到项目配置,如mysql 的配置文件:
工程化项目配置【iniparser的安装与使用】

自己写的一个ini配置文件👇:

[database]
ip       = 127.0.0.1 ;
port     = 3306 ;
user     = root ;
pwd      = 123456 ;
db       = mybike;[server]
port     = 9090;

我们先来看下ini的配置文件,例如我们的配置文件如下,[database]就是我们的俗称的区段,ipport就是字段,127.0.0.1和3306就是字段的值。
那么要如何对ini文件进行解析呢,首先想到的是不是使用文件流将文件中的内存读取出来,然后通过hash来进行key-value的存储,但是这样就会麻烦了,我们可以用别人写好的开源库iniparser来解析配置文件iniparser在github上的地址。


iniparser的安装

git clone https://github.com/ndevilla/iniparser
cd iniparser
make

make 以后会生成libiniparser.so.1以及libiniparser.a,而src目录下有dictionary.h以及iniparser.h
工程化项目配置【iniparser的安装与使用】
在写工程级的代码时,一般会有testsrc文件夹、confthird文件夹,其中third文件夹就是用来存放第三方头文件源文件以及库
在这里插入图片描述
当我们make以后生成库以及头文件,将库、头文件以及cpp文件放入到自己项目的third文件夹中
工程化项目配置【iniparser的安装与使用】


ini文件通过iniparser进行解析

先来展示下我的ini文件
shared_bike.ini

[database]
ip       = 127.0.0.1 ;
port     = 3306 ;
user     = root ;
pwd      = 123456 ;
db       = mybike;[server]
port     = 9090;

代码展示

configdef.h
将后续通过iniparser解析出来的数据保存到st_env_config结构中

#ifndef SHBK_COMMON_CONFIGDEF_H
#define SHBK_COMMON_CONFIGDEF_H
#include <string>
typedef struct st_env_config
{//数据库的配置std::string db_ip;unsigned short db_port;std::string db_user;std::string db_pwd;std::string db_name;//服务的配置unsigned short svr_port;st_env_config(){};st_env_config(const std::string& db_ip, unsigned int db_port, const std::string& db_user, \\const std::string& db_pwd, const std::string& db_name, unsigned short svr_port){this->db_ip    = db_ip;this->db_port  = db_port;this->db_user  = db_user;this->db_pwd   = db_pwd;this->db_name  = db_name;this->svr_port = svr_port;};st_env_config& operator =(const st_env_config& config){if (this != &config){this->db_ip    = config.db_ip;this->db_port  = config.db_port;this->db_user  = config.db_user;this->db_pwd	  = config.db_pwd;this->db_name  = config.db_name;this->svr_port = config.svr_port;}return *this;}
}_st_env_config;#endif//SHBK_COMMON_CONFIGDEF_H

iniconfig.h
将解析操作分装成一个类,将解析出来的结果保存到st_env_config结构中

#ifndef SHBK_COMMON_INICONFIG_H
#define SHBK_COMMON_INICONFIG_H
#include <string>
#include <stddef.h>
#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

iniconfig.cpp

#include "iniconfig.h"
//一会儿使用cmake将third文件夹包含进来
#include <iniparser/iniparser.h>
#include <iniparser/dictionary.h>
Iniconfig::Iniconfig():isLoaded(false)
{}
Iniconfig::~Iniconfig()
{}bool Iniconfig::loadFile(const std::string& path)
{//需要定义一个字典ini指针dictionary*   ini = NULL;//使用iniparser_load方法对ini文件进行解析,结果用字典来存ini = iniparser_load(path.c_str());if (ini==NULL){printf("cannot parse file: %s\\n", path.c_str());return false;}//区段:字段,如果这个字段不存在那么就是默认值127.0.0.1const 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", "bike");int   sport = iniparser_getint(ini, "server:port", 9090);//构造st_env_config结构体_config = st_env_config(std::string(ip), port, std::string(user), \\std::string(pwd), std::string(db), sport);//释放字典iniparser_freedict(ini);isLoaded = true;return true;
}const st_env_config&  Iniconfig::getconfig()
{return _config;
}

main.cpp

#include "iniconfig.h"
#include "configdef.h"//后续执行命令:xx.exe ./conf/shared_bike.ini
int main(int argc,char** argv)
{if(argc!=2){printf("Please input shbk <config file path>!\\n");return -1;}Iniconfig config;if(!config.loadFile(std::string(argv[1]))){printf("load %s is failed.\\n",argv[1]);return -2;}st_env_config conf_args = config.getconfig();printf("[database] ip:%s port:%d user:%s\\n",conf_args.db_ip.c_str(),conf_args.db_port,conf_args.db_user);return 0;
}

iniparser解析数据的流程

1、创建字典

//定义一个字典ini指针
dictionary*   ini = NULL;

2、加载数据

//使用iniparser_load方法对ini文件进行解析,结果用字典来存
ini = iniparser_load(path.c_str());

3、读取字典中的数据(可以将字典中的数据转存到一个类中进行保存)

//区段:字段,如果这个字段不存在那么就是默认值127.0.0.1
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", "bike");
int   sport = iniparser_getint(ini, "server:port", 9090);

什么是区段和字段呢?👇
工程化项目配置【iniparser的安装与使用】


cmake设计

要使用cmake来对这几个文件进行编译链接,所以来来看看俺的目录结构吧:
工程化项目配置【iniparser的安装与使用】

可以看到有两个CMakeLists.txt,里层的CMakeLists.txt是为了生成一个libcommon.a的库,在这个库中实现了一个类Iniconfig,它使用了iniparser对ini文件进行解析,并将结果存入到一个st_env_config类中,而外层CMakeLists.txt就是为了执行main函数,将libcommon.a进行使用,最终看到解析ini文件之后的结果【很多注释都在cmake的语句中了,如果对于cmake不熟悉的同学可以仔细看看下面的注释】

和main函数同级的外层CMakeList.txt

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(myBike)# 包含头文件目录
INCLUDE_DIRECTORIES(./common)
INCLUDE_DIRECTORIES(../third/include)# 包含库目录
LINK_DIRECTORIES(../third/lib/iniparser)
LINK_DIRECTORIES(./common)# 用来显式的定义变量
# 设置编译选项
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic -Wall -m64 -pipe -std=c++0x -lrt -Wno-reorder -Wdeprecated-declarations")# 收集指定目录下的文件名列表保存到变量中
aux_source_directory(. SOURCE_FILES)ADD_EXECUTABLE(myBike ${SOURCE_FILES})# 将具体的库链接上去
TARGET_LINK_LIBRARIES(myBike common)
TARGET_LINK_LIBRARIES(myBike iniparser)# 执行common文件夹下的CMakeLists.txt(这个操作就是生成libcommon.a)
ADD_SUBDIRECTORy(common)

common文件夹中的里层CMakeList.txt

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)# 收集指定目录下的文件名列表保存到变量中
aux_source_directory(. SOURCE_COMMON_FILES)
# 将这些个文件构建成一个库
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)# 将iniparser的库链接到common上
TARGET_LINK_LIBRARIES(common iniparser)
# TARGET_LINK_LIBRARIES(common dl)

运行结果:
工程化项目配置【iniparser的安装与使用】


结语

在本文中,我们介绍了如何使用iniparser库在Linux中解析INI文件,并使用CMake来构建我们的项目。我们首先简单展示了INI文件的格式,然后演示了如何使用iniparser库来读取INI文件中的配置信息。接下来,我们学习了如何使用CMake来配置我们的项目,并编写了CMakeLists.txt文件。最后,我们演示了如何使用CMake来构建我们的项目,并成功地解析了INI文件中的配置信息。

通过本文,我希望读者能够了解如何在Linux中使用iniparser库来解析INI文件,并学习如何使用CMake来构建C++项目。在实际工作中,配置文件是非常常见的,而INI文件作为其中的一种格式也是非常重要的。因此,掌握使用iniparser库来解析INI文件的方法,将有助于我们更加高效地处理配置文件。此外,使用CMake来构建C++项目也是一个非常重要的技能,它可以帮助我们更好地管理和组织我们的代码。

感谢您的阅读,希望本文对您有所帮助!