C:C++服务器开发的必备利器–libconfig

程序肯定需要一份配置文件,要不然,自己的程序不是“可配置”的,自己都不好意思往“高大上”靠拢。言归正传,以前自己写代码,配置文件的读写都是各式各样的,有用过xml,有用过其他项目copy过来的。看开源代码的时候,也是各式各样的,比如redis的,Nginx等等。有时候就在想,配置文件的解析还真是麻烦,要自己处理一堆的字符串,有空的时候自己整理一下Nginx的源码,复用Nginx的配置代码,加强自己的代码库。但最近才发现,原来已经有一个很优秀的C/C++配置库libconfig一直在等着我了。

认识libconfig

libconfig库的官方网站在:http://www.hyperrealm.com/libconfig/

一个配置项,可以理解为我们最常见的key-value的形式。key就是你的配置的名字了。那优秀就优秀在value上了。value支持的类型有:

1、常见的数据类型:

整数(int):可以用10进制和16进制表示。0x打头的数字libconfig会自动解析为16进制的数字。

64位整数(int64_t):在数字的后面加上L即可。

浮点数(float):个人不太喜欢用这个类型。

布尔数(bool):true或者false。不区分大小写。

字符串(string):这个字符串非常强大。

a、支持转义字符'\\’, ‘\f’, ‘\n’, ‘\r’,‘\x’ and ‘\t’

b、相邻的字符串libconfig会自动拼接。这样太常的内容,我们可以多行来写,可读性非常好。比如:

example = “hello world”; 等价于

example = “hello”

” world”;

【注意】
我们可以使用’=’,也可以使用’:’来作为赋值号。既然是C/C++程序员,还是使用’=’号看得舒服一些。

和C/C++的注释一样,/**/就是跨行的注释。 //就是单行注释。当然还支持脚本语言的注释符号##也是单行注释。但是特殊的是,如果注释符在双引号中使用,那就不再是注释符了,libconfig会解析为正常的明文。

2、数组结构

和平常我们使用的数组是一样一样的,数组的各个元素都必须是相同的数据类型。

3、群组结构

这个可以理解为一个容器。这个容器里面,我们可以放置很多个配置项。当然这些配置项的value也可以继续是群组。

4、列表结构

这个列表和我们C++常用的STL里的list结构可不太一样。这个列表结构里面的元素不要求具备相同的数据类型,元素1是int,元素2可以是string,元素3可以是数组,元素4可以是一个群组,元素5可以是另一个列表。

可以说,正是因为value的多姿多彩,才给了我们程序员无限的发挥空间。通过群组结构和列表结构,我们可以很方便灵活的进行各种变态的配置读取。除了读取配置,可不要忘记了libconfig还有两只手的哦:必要的时候,我们可以把内存里面的一些值,通过libconfig生成一份标准的配置文件。

体验libconfig

动手用libconfig进行一个hello world的配置吧!把value支持的所有数据类型都用上,加深理解。

//example.conf

/* 这个叫Settings */
version = "1.0.0.0";

/* 这个叫Groups */
log = {
  log_path = "../logs/sys.log";  /* 日志文件路径 */
  log_size = 1024000000L;        /* 日志文件大小 */
  log_level = 20000;             /* 日志等级 */
};

/* 这个叫Lists */
// 业务服务器列表
server = (
  {
    addr = "10.1.88.1";
    port = 9090;
  },
  {
    addr = "10.1.88.2";
    port = 9090;
  },
  {
    addr = "10.1.88.3";
    port = 9090;
  }
);

// 测试配置
test = {
  // 这个是数组结构。
  uin = [10086L, 10087L, 10088L, 10089L];  /* 测试号码 */
  /* 测试服务器 */
  server = {
    addr = "10.1.99.1";
    port = 9090;
  };
};

值得说明的是,libconfig是通过路径来读取某一个配置的。比如log.log_path这个路径对应的是log_path这个配置项,

server.[0].addr这个路径对应的是业务服务器列表的第一个元素里面的addr这个配置项。

libconfig的代码样例

不写一段hello world的代码,是算不上真正接触了libconfig的。libconfig提供了C和C++的API。先用C++来爽一下吧。

首先就是要下载安装libconfig的库。这个很简单,到官网下载,然后./configure & make & make install就可以了。

#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <libconfig.h++>

using namespace std;
using namespace libconfig;


int main(){
  Config cfg;

  /*
    解析配置文件。
  */
  try
  {
    cfg.readFile("example.conf");
  }
  catch(const FileIOException &fioex)
  {
    std::cerr << "I/O error while reading file." << std::endl;
    return(EXIT_FAILURE);
  }
  catch(const ParseException &pex)
  {
    std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
              << " - " << pex.getError() << std::endl;
    return(EXIT_FAILURE);
  }

  /* 从配置文件中,得到version这个配置项的值。 */
  try
  {
    string version = cfg.lookup("version");
    cout << "version: " << version << endl << endl;
  }
  catch(const SettingNotFoundException &nfex)
  {
    cerr << "No 'version' setting in configuration file." << endl;
  }

  /* 从配置文件中,得到日志相关配置值 */
  try
  {
    string log_path = cfg.lookup("log.log_path");
    cout << "log_path: " << log_path << endl;

    int64_t log_size = cfg.lookup("log.log_size");
    cout << "log_size: " << log_size << endl;

    int log_level = cfg.lookup("log.log_level");
    cout << "log_level: " << log_level << endl << endl;
  }
  catch(const SettingNotFoundException &nfex)
  {
    cerr << "log setting mistake in configuration file." << endl;
  }

  try
  {
    const Setting &server = cfg.lookup("server");
    int count = server.getLength();
    cout << "server.count = " << count << endl;

    for (int i = 0; i < count; i++)
    {
      string addr = "";
      int port = 0;
      if (!server[i].lookupValue("addr", addr)
          || !server[i].lookupValue("port", port))
      {
        cerr << "lookupValue error" << endl;
        continue;
      }

      cout << "server[" << i << "] = " << addr << ":" << port << endl;
    }

    {
      string addr = "";
      int port = 0;
      if (!cfg.lookupValue("server.[0].addr", addr)
          || !cfg.lookupValue("server.[0].port", port)) {
        cerr << "lookupValue 'server.[0].addr' error" << endl;
      }
      else
        cout << "server[0] = " << addr << ":" << port << endl << endl;
    }
  }
  catch(const SettingNotFoundException &nfex)
  {
    cerr << "server setting mistake in configuration file." << endl;
  }

  try
  {
    const Setting& root = cfg.getRoot();
    const Setting &uin = root["test"]["uin"];
    int count = uin.getLength();
    cout << "uin.count = " << count << endl;

    const Setting &test = cfg.lookup("test");
    const Setting &test2 = cfg.lookup("test.uin");
    for (int i = 0 ; i < count; i++)
    {
      int64_t u = test["uin"][i];
      int64_t uu = uin[i];
      int64_t uuu = test2[i];
      cout << "uin[" << i << "] = " << u << ", " << uu << ", " << uuu << endl;
    }

    const Setting &server = root["test"]["server"];
    string addr = "";
    int port = 0;
    if (!server.lookupValue("addr", addr)
        || !server.lookupValue("port", port))
    {
      cerr << "test server lookupValue error" << endl;
    }
    else
      cout << "test server = " << addr << ":" << port << endl << endl;
  }
  catch(const SettingNotFoundException &nfex)
  {
    cerr << "test setting mistake in configuration file." << endl;
  }
}

编译和运行一下:

version: 1.0.0.0

log_path: ../logs/sys.log
log_size: 1024000000
log_level: 20000

server.count = 3
server[0] = 10.1.88.1:9090
server[1] = 10.1.88.2:9090
server[2] = 10.1.88.3:9090
server[0] = 10.1.88.1:9090

uin.count = 4
uin[0] = 10086, 10086, 10086
uin[1] = 10087, 10087, 10087
uin[2] = 10088, 10088, 10088
uin[3] = 10089, 10089, 10089
test server = 10.1.99.1:9090

转载自:https://www.cnblogs.com/kex1n/p/6651258.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值