史上最全libconfig用法及配置详解

Libconfig是一个用于读写结构化配置文件的库,支持C和C++,适用于多种操作系统。配置文件包含设置,如标量值、数组、群组和列表,具有良好的可读性和类型感知。API提供了读写文件、查找设置和获取值的方法。在多线程环境中,libconfig是可重入但线程不安全的,需要注意同步。安装过程包括编译、安装和配置环境变量。
摘要由CSDN通过智能技术生成

一、libconfig是什么

        Libconfig是一个结构化的配置文件库,它可以定义一些配置文件,例如test.cfg . 它比xml可读性更好,而且更简洁。而且不像xml,它是 type-aware类型自我感知的,因此不需要做string parsing 。        

        Libconfig 是用于读取、操作和写入结构化配置文件的库。 该库具有完全可重入的解析器,并包括 C 和 C++ 编程语言的绑定。该库可在现代 POSIX 兼容系统上运行,例如 Linux、Solaris 和 Mac OS X (Darwin),以及 Microsoft Windows 2000/XP 及更高版本(使用 Microsoft Visual Studio 2005 或更高版本,或 GNU 工具链通过 MinGW 环境)。

二、libconfig的解析方式    

        一个配置由一组setting构成,setting由名字(name)关联,并有相应的值(value)。一个值(value)可以是以下任意一种类型:

        标量值(scalarvalue):整型、64位整型、浮点数、布尔值或者字符串

        数组(array):一组标量值的序列,所有的标量值必须为同一类型

        群组(group):多个setting的集合

        列表(list):一组值(value)的序列,各个值可(value)以分别为不同的类型,其他的列表也可以包含其中。

        包含在配置中的某个setting可以用path来唯一定义,path用点号分隔连接多个名字(name),由最顶层的群组(group)开始,到setting自身结束。path中的每个名字都是一个setting的名字;如果这个setting没有名字,那是因为它是数组(array)或列表(list)中的一个元素。用方括号包含一个整型索引值可以用来表示它的名字。

        值的数据类型由值本身的格式确定。如果值用双引号括起来,则将其视为字符串。如果它看起来像一个整数或浮点数,则按原样处理。如果它是值 TRUE、true、FALSE 或 false(或这些标记的任何其他大小写混合版本,例如 True 或 FaLsE)之一,则将其视为布尔值。如果它由括在方括号中的逗号分隔值列表组成,则将其视为数组。如果它由括在括号中的逗号分隔值列表组成,则将其视为列表。任何不满足这些条件的值都被视为无效并导致解析错误。所有名称都区分大小写。它们只能由字母数字字符、破折号 (‘-’)、下划线 (‘_’) 和星号 (‘*’) 组成,并且必须以字母或星号开头。不允许使用其他字符。

        在 C 和 C++ 中,整数、64 位整数、浮点数和字符串值分别映射到本机类型 int、long long、double 和 const char *。 boolean 类型在 C 中映射为 int,在 C++ 中映射为 bool。以下部分更详细地描述了配置文件语法的元素:

  • setting

一个setting的格式如下:

name= value;或者name: value;结尾的分号是必须要有的,空白字符会被忽略;value可以是标量值、数组、群组或者列表。

  • 群组(group)

一个群组的格式如下:{setting1,setting2, …},一个群组可以包含任意个setting,但是在群组中,每个setting的名字必须是唯一的。

  • 数组(array)

一个数组的格式如下:[value,value, …],一个数组可以有零个或者多个元素,但是每个元素都必须是相同类型的标量值。

  • 列表(list)

一个列表的格式如下:(value,value, …),一个列表可以有零个或者多个元素,而且每个元素可以分别是标量值、数组、群组或其他列表。

  • 整型值

整型值(int)可以用两种方式表示:十进制数,由0-9组成,并且可以带+或-;十六进制数,0x打头并且用十六进制数表示。

  • 64位整型值

64位整型值(longlong)表示方法和整型值基本一致,但是需要在最后加上L来表明它是一个64位整型值。比如0L表示一个64位的0值。

  • 浮点值

浮点值由一个十进制数,可以带正负符号,然后带上一个可选的指数。这个可选的指数又由字母E或者e加上一个可选的正负符号再加上具体的数字。

  • 布尔值

布尔值的取值只能是true和false,包括另外大小写混合的写法,比如tRue或FaLSe。

  • 字符串

字符串是由双引号引起来的任意文本。字符串里的双引号由转义符\”替代,其他的转义符比如\\、\f、\r、\n、\t都可以被辨认,并且与通常的理解一致。

另外,转义符\x也被支持。它后面必须跟上刚好两个十六进制数,用来表示8位的ASCII值,比如\xFF表示值为0xFF的ASCII码。

其他的转义符都不被支持。

相邻的两个字符串会被自动连接,就像C的编码规则一样。在把一个很长得字符串格式化为很短的字符串的时候,就会很有用。比如,下面三种写法的字符串都是等价的。

"Thequickbrownfoxjumpedoverthelazydog."

"Thequickbrownfox"

"jumpedoverthelazydog."

"Thequick"/*注释*/"brownfox"//其他注释

"jumpedoverthelazydog."

  • 注释

在配置文件中允许三种类型的注释

脚本风格的注释:从#开始到行尾的内容都为注释。

C风格的注释:/*和*/之间的内容,即使是跨行的,都被认为是注释。

C++风格的注释:从//开始到行尾的内容都被认为是注释。

如预料的一样,注释符在双引号字符串中出现,会被认为是字符串的文本而不是注释符。

在读取配置的时候,注释内容会被忽略,它们不会被认为是配置的一部分。因此,如果配置回写到文件中,原配置文件中的一些注释会丢失。

  • 包含指令

一个配置文件可能包含了另外一个配置文件的内容,这时就要用到包含指令。这个指令产生的效果就是在包含点内联了那个文件的内容。

一个包含指令必须出现在它所在的那一行中,格式如下:

@include“filename”

文件名中反斜杠和双引号必须用转义符\\和\”来替代。

举例说明,观察下面两个配置文件

#file:quote.cfg

quote="Criticismmaynotbeagreeable,butitisnecessary."

"Itfulfilsthesamefunctionaspaininthehuman"

"body.Itcallsattentiontoanunhealthystateof"

"things.\n"

"\t--WinstonChurchill";

#file:test.cfg

info:{

name="WinstonChurchill";

@include"quote.cfg"

country="UK";

};

包含文件最大只能嵌套10层,突破这个限制会产生一个分析错误。

与注释类似,包含指令也不是配置文件句法的一部分。包含指令在配置文件被分析之前就已经被处理了。因此,当配置回写回文件的时候,包含指令不会被保留。目前还不支持让程序把包含指令插入到配置文件中。

三、使用libconfig注意事项

1. C++API 头文件 #include <libconfig.h++> ,命名空间:using namespace libconfig;

2.多线程使用问题:

  (1)libconfig是完全可重入的,库中函数不使用全局变量和不保持成功调用间的状态。所以两个独立配置文件在两个不同线程间并发操作可以是安全的;

  (2)libconfig是线程不安全,libconfig不考虑系统线程模型。所以一个配置文件的实例被多个线程获取,必须使用同步机制(例如读写锁或互斥锁)来保护。

  (3)libconfig不是异步安全,不能在信号句柄中调用

  (4)libconfig不能保证取消安全。因为它不知道主机系统的线程模型,库不包含任何线程取消点。在大多数情况下这将不是多线程程序的问题。但是,请注意一些库中的例程(即那些从/到文件读取/写入配置的程序)流)使用可能会阻止的C库例程执行I/O;是否这些C库例程是取消安全的,取决于主机系统。

3.C++API

  C++API使用Config类和Setting类,因为不提供公有的copy constructor or assignment operator,所以在函数参数中传递时使用引用或指针方式

四、libconfig常用API

        1、Method on Config: void readFile (const char * filename)

readFile() 方法从名为 “filename” 的文件中读取并解析配置。 如果发生解析错误,则抛出 ParseException。 如果无法读取文件,则抛出 FileIOException。

        2、Method on Config: void writeFile (const char * filename)

writeFile() 方法将配置写入名为 “filename” 的文件。 如果无法写入文件,则会引发 FileIOException。

        3、Method on Config: Setting & lookup (const std::string &path)

             Method on Config: Setting & lookup (const char * path)

这两个方法定位由路径指定的Setting。 如果未找到请求的Setting,则抛出 SettingNotFoundException。返回值为Setting对应的value。

        4、Method on Config: Setting & getRoot ()

此方法返回Setting的根设置,是一个Group。

        5、Method on Config: bool lookupValue (const char *path, bool &value)

              Method on Config: bool lookupValue (const std::string &path, bool &value)

              Method on Config: bool lookupValue (const char *path, int &value)

              Method on Config: bool lookupValue (const std::string &path, int &value)

              Method on Config: bool lookupValue (const char *path, unsigned int &value)

              Method on Config: bool lookupValue (const std::string &path, unsigned int &value)

              Method on Config: bool lookupValue (const char *path, long long &value)

              Method on Config: bool lookupValue (const std::string &path, long long &value)

              Method on Config: bool lookupValue (const char *path, float &value)

              Method on Config: bool lookupValue (const std::string &path, float &value)

              Method on Config: bool lookupValue (const char *path, double &value)

              Method on Config: bool lookupValue (const std::string &path, double &value)

              Method on Config: bool lookupValue (const char *path, const char *&value)

              Method on Config: bool lookupValue (const std::string &path, const char *&value)

              Method on Config: bool lookupValue (const char *path, std::string &value)

              Method on Config: bool lookupValue (const std::string &path, std::string &value)

这些方法是使用给定path查找Setting值的便捷方法。 如果找到该Setting并且是适当的类型,则将该值存储在 value 中并且该方法返回 true。 否则, value 保持不变并且该方法返回 false。 这些方法不会抛出异常。

五、Linux下 C/C++ libconfig安装及配置

        libconfig下载地址:https://hyperrealm.github.io/libconfig/

        1、解压并安装:

  1. tar xzvf libconfig-1.7.2.tar.gz

  2. cd libconfig-1.7.2

  3. sudo ./configure

  4. sudo make

  5. sudo make check

  6. sudo make install

         2、配置环境变量,libconfig默认安装在/usr/local/lib下,将此路径添加到path中

export LD_LIBRARY_PATH=/usr/local/lib   //配置环境变量

sudo ldconfig -V                                          //查看是否安装

         3、测试

        1)测试C版本

  1. cd examples/c/

  2. gcc example1.c -o example1 -lconfig

  3. ./example1

         2)测试C++版本

  1. cd examples/c++/

  2. g++ example1.cpp -lconfig++ -o example1

  3. ./example1 

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
libconfig是一个C/C++库,用于处理配置文件。使用libconfig可以轻松地读取和写入各种格式的配置文件,包括INI、XML和JSON格式。 以下是libconfig的基本用法: 1. 安装libconfig 可以使用包管理器在Linux上安装libconfig。在Ubuntu上,可以使用以下命令进行安装: ``` sudo apt-get install libconfig-dev ``` 在Windows上,可以从libconfig的官方网站下载预编译的二进制文件,并将其添加到项目中。 2. 创建配置文件 可以使用任何文本编辑器创建配置文件。例如,以下是一个简单的INI格式示例: ``` ; Sample configuration file [database] host = "localhost" port = 3306 username = "root" password = "password123" database = "mydb" ``` 3. 读取配置文件 要读取配置文件,需要创建一个libconfig对象,并使用它来打开配置文件并读取值。以下是一个示例代码: ```c++ #include <iostream> #include <libconfig.h++> using namespace std; using namespace libconfig; int main() { Config cfg; try { cfg.readFile("config.ini"); string host = cfg.lookup("database.host"); int port = cfg.lookup("database.port"); string username = cfg.lookup("database.username"); string password = cfg.lookup("database.password"); string database = cfg.lookup("database.database"); cout << "Host: " << host << endl; cout << "Port: " << port << endl; cout << "Username: " << username << endl; cout << "Password: " << password << endl; cout << "Database: " << database << endl; } catch(const FileIOException &fioex) { cerr << "I/O error while reading file." << endl; return(EXIT_FAILURE); } catch(const ParseException &pex) { cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine() << " - " << pex.getError() << endl; return(EXIT_FAILURE); } return(EXIT_SUCCESS); } ``` 在代码中,我们首先创建了一个Config对象。然后,我们使用readFile()方法打开配置文件。接下来,我们使用lookup()方法获取配置文件中的值,并将其存储在变量中。最后,我们使用cout打印出这些值。 4. 写入配置文件 要写入配置文件,需要创建一个Config对象,并使用它来设置配置文件中的值。以下是一个示例代码: ```c++ #include <iostream> #include <libconfig.h++> using namespace std; using namespace libconfig; int main() { Config cfg; try { cfg.readFile("config.ini"); cfg.lookup("database.host") = "newhost.com"; cfg.lookup("database.port") = 1234; cfg.lookup("database.username") = "newuser"; cfg.lookup("database.password") = "newpassword"; cfg.lookup("database.database") = "newdb"; cfg.writeFile("config.ini"); } catch(const FileIOException &fioex) { cerr << "I/O error while reading/writing file." << endl; return(EXIT_FAILURE); } return(EXIT_SUCCESS); } ``` 在代码中,我们首先创建了一个Config对象。然后,我们使用readFile()方法打开配置文件。接下来,我们使用lookup()方法设置配置文件中的值。最后,我们使用writeFile()方法将更改写入配置文件。 这就是libconfig的基本用法。可以查阅libconfig的官方文档,了解更多高级用法
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值