使用背景
在写项目代码的时候,有时会需要配置参数和初始设置,其实使用宏定义也是可以解决的,但是当需要修改参数的时候,就需要去修改源码,为了不随便去动源码,我们可以将信息写在配置文件中,如果配置信息有变动的时候我们只需要修改配置文件即可。常见的配置文件类型有:
ini 、properties、json、xml、yaml、toml、HOCON、plist等,其关于他们较为详细的介绍在这里常用配置文件格式
其中ini文件是一个无固定标准格式的配置文件,它以简单的文字与简单的结构组成,常常使用在Windows操作系统。ini文件的命名来源,是取自英文“初始(initial)”的首字缩写,正与它的用途——初始化程序响应。
提示:以下是本篇文章正文内容,下面案例可供参考
一、iniparser的介绍
ini的文件格式比较简单,分为节(section),名称(name),值(value)和注释。而iniparser库中的函数就是针对这类文件类型进行解析和修改的一个解析器。ini文件的一般格式为:
这里的 conf_info 和 apartment叫做 section,等号左边的叫名称(name),等号右边的叫值(value),多个这样的键值对可以归到一个section下,section定义要独立一行,并用中括号括起来。
在section声明下键值对都会与该section关联起来,一个section的作用域会在一个section声明的地方结束,如果没有下个section的声明,那么该section的结束地方就是该文件末尾。
section不可嵌套,不同section下的key的名称是可以相同的,因为在读取INI配置文件的时候,是通过section:key来表示的,因此同一个section下的key是唯一的,不能重复的。
iniparser库处理名称的时候,会统一换成小写,所以section和property的名称命名是大小写无关的。
注释以分号开头
二、下载安装
可以通过如下命令下载iniparser这个库
git clone https://github.com/ndevilla/iniparser
进入iniparser文件夹,再进入src,事实上,我们最需要的就是这四个文件:dictionarry.h dictionary.c iniparser.h iniparser.c 这四个文件。
在要使用到ini文件读取的时候,就将头文件包含进去,在编译的时候将c文件包含进去,就能调用库中的函数了(后面有示例)
三、常用的函数
iniparser.h中常用的函数有如下,在使用函数的时候也可以直接去该文件下看,都会有说明,包括函数功能、参数、返回值。
/*-------------------------------------------------------------------------*/
/**
@brief Get name for section n in a dictionary.
@param d Dictionary to examine
@param n Section number (from 0 to nsec-1).
@return Pointer to char string
This function locates the n-th section in a dictionary and returns
its name as a pointer to a string statically allocated inside the
dictionary. Do not free or modify the returned string!
This function returns NULL in case of error.
*/
/*--------------------------------------------------------------------------*/
const char * iniparser_getsecname(const dictionary * d, int n);
/*-------------------------------------------------------------------------*/
/**
@brief Get the number of keys in a section of a dictionary.
@param d Dictionary to examine
@param s Section name of dictionary to examine
@return Number of keys in section
*/
/*--------------------------------------------------------------------------*/
int iniparser_getsecnkeys(const dictionary * d, const char * s);
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key
@param d Dictionary to search
@param key Key string to look for
@param def Default value to return if key not found.
@return pointer to statically allocated character string
This function queries a dictionary for a key. A key as read from an
ini file is given as "section:key". If the key cannot be found,
the pointer passed as 'def' is returned.
The returned char pointer is pointing to a string allocated in
the dictionary, do not free or modify it.
*/
/*--------------------------------------------------------------------------*/
const char * iniparser_getstring(const dictionary * d, const char * key, const char * def);
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key, convert to an int
@param d Dictionary to search
@param key Key string to look for
@param notfound Value to return in case of error
@return integer
This function queries a dictionary for a key. A key as read from an
ini file is given as "section:key". If the key cannot be found,
the notfound value is returned.
Supported values for integers include the usual C notation
so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
are supported. Examples:
- "42" -> 42
- "042" -> 34 (octal -> decimal)
- "0x42" -> 66 (hexa -> decimal)
Warning: the conversion may overflow in various ways. Conversion is
totally outsourced to strtol(), see the associated man page for overflow
handling.
Credits: Thanks to A. Becker for suggesting strtol()
*/
/*--------------------------------------------------------------------------*/
int iniparser_getint(const dictionary * d, const char * key, int notfound);
/*-------------------------------------------------------------------------*/
/**
@brief Set an entry in a dictionary.
@param ini Dictionary to modify.
@param entry Entry to modify (entry name)
@param val New value to associate to the entry.
@return int 0 if Ok, -1 otherwise.
If the given entry can be found in the dictionary, it is modified to
contain the provided value. If it cannot be found, the entry is created.
It is Ok to set val to NULL.
*/
/*--------------------------------------------------------------------------*/
int iniparser_set(dictionary * ini, const char * entry, const char * val);
/*-------------------------------------------------------------------------*/
/**
@brief Parse an ini file and return an allocated dictionary object
@param ininame Name of the ini file to read.
@return Pointer to newly allocated dictionary
This is the parser for ini files. This function is called, providing
the name of the file to be read. It returns a dictionary object that
should not be accessed directly, but through accessor functions
instead.
The returned dictionary must be freed using iniparser_freedict().
*/
/*--------------------------------------------------------------------------*/
dictionary * iniparser_load(const char * ininame);
/*-------------------------------------------------------------------------*/
/**
@brief Free all memory associated to an ini dictionary
@param d Dictionary to free
@return void
Free all memory associated to an ini dictionary.
It is mandatory to call this function before the dictionary object
gets out of the current context.
*/
/*--------------------------------------------------------------------------*/
void iniparser_freedict(dictionary * d);
dictionary.h中的函数我就不展示了,大家直接cat查看就行了。事实上iniparser是对dictionary中的函数再封装,为了方便用户使用。
四、读取和修改INI文件示例
配置文件的内容如下:
[conf_info]
username =123
passwd =1122334455
[apartment_number]
username =xx
site =7#001
测试代码如下:
#include <stdio.h>
#include <stdlib.h>
#include "iniparser.h"
int main()
{
dictionary *ini;
ini = iniparser_load("./ini");
//printf first section name
printf("%s\n",iniparser_getsecname(ini,0));
//get integer
int username = iniparser_getint(ini,"conf_info:username",-1);
printf("conf_info:username: %d\n",username);
//reset key
iniparser_set(ini,"apartment:username","xixi");
const char *name = iniparser_getstring(ini,"apartment:username","NULL");
printf("apartment:username: %s\n",name);
return 0;
}
终端的执行命令:
gcc main.c iniparser.c dictionary.c
其运行结果如下:
需要注意的是,这里修改的ini的参数,在修改之后打印出来确实是修改了,但是配置文件ini中并不会被修改。