百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

一文告诉你Linux下如何用C语言实现ini配置文件的解析和保存

ahcoder 2025-03-10 11:58 12 浏览

嵌入式项目开发中,会有很多功能模块需要频繁修改参数,Linux下我们可以通过ini格式的文件保存配置信息。

本文通过开源库iniparser,详细讲解如何用C语言实现ini文件的参数解析和配置保存。

本文代码实例获取方式见文末



一、ini文件

1 什么是 ini文件

  • INI(Initialization File)文件是一种简单直观的数据存储格式,常用于配置应用程序的初始化设置。这种文件通常包含若干个节(section)和键值对(key-value pairs)。INI文件的每一部分都是自描述性的,易于阅读和编辑,使得非程序员也能轻易理解并修改配置参数。
  • INI文件因其简单易用性而在许多编程语言中广泛应用,尤其是在Windows操作系统中,很多应用程序都采用INI文件作为配置文件。当然,随着XML、JSON等更丰富、更结构化的数据交换格式的普及,INI文件在现代应用程序中的使用相对减少,但在一些轻量级应用或对启动速度有较高要求的情况下,仍然是一种常见且实用的配置文件格式。

2 ini文件结构

  • 节(Section):INI文件中的各个部分通过方括号 [] 包裹的名称来定义,例如 **[Section1]**。每个节可以包含多个键值对。
  • 键值对(Key-Value Pairs):键和值之间用等号 = 分隔,如 key1=value1。键通常是描述性质的字符串,而值则可以是字符串、数字或其他类型的数据。
  • 注释:注释行以分号 ; 开始,直到行尾都被视为注释内容,不会被程序解析。
  • 多行值:某些INI解析器允许值跨越多行,通常通过在行尾添加反斜杠 \ 来延续到下一行

3 ini文件举例

;author yikoupeng

[BASIC_INFO]
version                = V1.1.1.1
user                   = yikou
number                 = 999


[FTP]
ftppath                = /home/ftp
ftpuser                = ftp
ftppass                = 123456
port                   = 21

......

其中:

  • 注释以分号(;)开头
  • [BASIC_INFO]、[FTP]就是组名,
  • 组成员有“version”........“ftppath”...

注意:

每个组下的key是唯一不能重复的,但不同组下可以存在相同的key.

二、 iniparser库

1. iniparser介绍

iniparser是一个C语言库,用于解析和操作 INI 格式的配置文件,是针对INI文件的开源解析器。

iniparser可以对配置文件进行解析、添加、修改、删除等操作。

git地址如下:

 https://github.com/ndevilla/iniparser

2. iniparser的安装

1、下载iniparser

wget https://codeload.github.com/ndevilla/iniparser/tar.gz/refs/tags/v4.1 -O iniparserv4.1.tar.gz

2、解压

tar -zxvf iniparserv4.1.tar.gz  

3、进入目录

cd iniparser-4.1/
peng@ubuntu:~/work/iniparser-4.1$ ls
AUTHORS  doc  example  FAQ-en.md  FAQ-zhcn.md  html  INSTALL  libiniparser.a  libiniparser.so.1  LICENSE  Makefile  README.md  src  test

4、进入src文件夹可以看到我们所需要的主要代码

peng@ubuntu:~/work/iniparser-4.1$ cd src/
peng@ubuntu:~/work/fdw/code/config/iniparser-4.1/src$ ls
dictionary.c  dictionary.h   iniparser.c  iniparser.h 

如果想移植该程序到我们的项目中,只需要将这几个文件添加到工程对应目录,编译进工程即可。

三、iniparser API(应用编程程序接口)

dictionary.h里面声明了一些直接解析ini file的API,iniparser.h头文件里面声明了一些提供用户操作的API。

iniparser.h里面的API是对dictionary.h里面API的再次封装,以提供用户友好性。

iniparser.h头文件里面的主要API

1 加载ini文件

/*
   *  @brief  从ini格式的配置文件中加载数据
   *  @param  [IN]  ininame  要打开的ini格式文件            
   *  @return != NULL 返回一个指向dictionary结构的指针
   *          == NULL 加载ini文件失败
  */
  dictionary * iniparser_load(const char *ininame);

2 获取键值

  • /*
    * @brief 获取指定键(key)对应的字符串类型的值
    * @param [IN] d dictionary结构的指针
    * @param [IN] key 要查找的键,通常格式为 "section:key",表示要获取哪个节(section)下的哪一项(key)的值。
    * @param [IN] def 当键不存在或者其值不是字符串时的默认返回值。如果没有找到对应键,函数将返回此默认值。
    * @return 如果找到了相应的键,返回键值对应字符串
    * 如果没有找到匹配的键,返回def指定的字符串值
    */

    const char * iniparser_getstring(const dictionary *d, const char *key, const char *def);

    /*
    * @brief 获取指定键(key)对应的整数值
    * @param [IN] d dictionary结构的指针
    * @param [IN] key 要查找的键,通常格式为 "section:key",表示要获取哪个节(section)下的哪一项(key)的值。
    * @param [IN] notfound 当键不存在或者其值不能被转换为整数时,函数将返回这个默认值。
    * @return 如果找到了相应的键,并且其值可以被成功转换为整数,则返回该整数值。
    * 如果没有找到匹配的键,或者该键对应的值无法转换为整数,则返回 notfound 参数提供的默认值。
    */

    int iniparser_getint(const dictionary * d, const char * key, int notfound);

    /*
    * @brief 获取指定键(key)对应的浮点型值
    * @param [IN] d dictionary结构的指针
    * @param [IN] key 要查找的键,通常格式为 "section:key",表示要获取哪个节(section)下的哪一项(key)的值。
    * @param [IN] notfound 当键不存在或者其值无法转换为双精度浮点数时,函数返回的默认值。
    * @return 如果找到了相应的键,并且其值能成功转换为一个双精度浮点数,则返回该浮点数。
    * 如果没有找到匹配的键,或者键的值不能被解释为一个有效的双精度浮点数,则返回 notfound 参数所提供的默认值。
    */

    double iniparser_getdouble(const dictionary *d, const char *key, double notfound);

3 设置键值

/*
  *  @brief  设置或修改 ini  配置文件中某个键值对
  *  @param  [IN]  d  dictionary结构的指针   
  *  @param  [IN]  entry  字符串形式的键值对标识符,格式通常是 "section:key",表明您要在哪个节(section)下的哪个键(key)上设置或修改值(val)。
  *      key值存在则修改对应val,key值不存在则会新增
  *  @param  [IN]  val: 要设置的新值,作为字符串传递。
  *  @return 返回0表示设置成功
  */
  int iniparser_set(dictionary *ini, const char *entry, const char *val);

4 移除键值

  • /*
    * @brief 移除 ini 配置文件中某个键值对
    * @param [IN] d dictionary结构的指针
    * @param [IN] entry 字符串形式的键名,包括可选的部分名称(section)和键(key)
    * 如果不指定key,则会移除整个section
    */

    void iniparser_unset(ini, const char *entry);

5 判断键是否存在

  • /*
    * @brief 判断 ini 配置文件是否存在某个键值
    * @param [IN] d dictionary结构的指针
    * @param [IN] entry 字符串形式的键值对标识符,格式通常是 "section:key"
    * @return 返回1表示存在,返回0表示不存在
    */

    int iniparser_find_entry(const dictionary *ini, const char *entry);

6 获取section个数

  • /*
    * @brief 获取ini配置文件中section的数量
    * @param [IN] d dictionary结构的指针
    * @return 成功返回section个数,失败返回 -1
    */

    int iniparser_getnsec(const dictionary * d);

    /*
    * @brief 获取某个section值
    * @param [IN] d dictionary结构的指针
    * @param [IN] n 指定获取第几个section值
    * @return 成功返回获取到的section值,失败返回NULL
    */

    const char *iniparser_getsecname(const dictionary * d, int n);

7 获取section下key个数

  • /*
    * @brief 获取ini配置文件中某个section的key个数
    * @param [IN] d dictionary结构的指针
    * @param [IN] s section
    * @return 返回指定section下的key个数
    */

    int iniparser_getsecnkeys(dictionary * d, char * s);

    /*
    * @brief 获取ini配置文件中某个section的所有key
    * @param [IN] d dictionary结构的指针
    * @param [IN] s section
    * @param [OUT] keys 通过这个参数输出key,也可以通过返回值获取
    * @return 成功返回指定section下的key,失败返回NULL
    */

    const char **iniparser_getseckeys(const dictionary *d, const char *s, const char **keys)

8 保存dictionary对象到文件中

  • /*
    * @brief 保存dictionary对象到文件中
    * @param [IN] d dictionary结构的指针
    * @param [IN] f 已打开的文件描述符
    */

    void iniparser_dump_ini(const dictionary *d, FILE *f);

9 释放dictionary对象

  • /*
    * @brief 释放dictionary对象
    * @param [IN] d dictionary结构的指针
    */

    void iniparser_freedict(dictionary * d);

10 api汇总

  • iniparser.h头文件里面的API
//获取dictionary对象的section个数  
int iniparser_getnsec(dictionary * d);  

 //获取dictionary对象的第n个section的名字  
char * iniparser_getsecname(dictionary * d, int n);

 //保存dictionary对象到file  
void iniparser_dump_ini(dictionary * d, FILE * f); 

 //保存dictionary对象一个section到file
void iniparser_dumpsection_ini(dictionary * d, char * s, FILE * f);  

 //保存dictionary对象到file 
void iniparser_dump(dictionary * d, FILE * f);  

//获取dictionary对象某个section下的key个数 
int iniparser_getsecnkeys(dictionary * d, char * s);  

//获取dictionary对象某个section下所有的key
char ** iniparser_getseckeys(dictionary * d, char * s);   

//返回dictionary对象的section:key对应的字串值  
char * iniparser_getstring(dictionary * d, const char * key, char * def); 

 //返回idictionary对象的section:key对应的整形值  
int iniparser_getint(dictionary * d, const char * key, int notfound); 

//返回dictionary对象的section:key对应的双浮点值  
double iniparser_getdouble(dictionary * d, const char * key, double notfound);  

 //返回dictionary对象的section:key对应的布尔值  
int iniparser_getboolean(dictionary * d, const char * key, int notfound);  

//设置dictionary对象的某个section:key的值  
int iniparser_set(dictionary * ini, const char * entry, const char * val); 

//删除dictionary对象中某个section:key
void iniparser_unset(dictionary * ini, const char * entry);  

//判断dictionary对象中是否存在某个section:key
int iniparser_find_entry(dictionary * ini, const char * entry) ;  

 //解析dictionary对象并返回(分配内存)dictionary对象
dictionary * iniparser_load(const char * ininame);

//释放dictionary对象(内存)  
void iniparser_freedict(dictionary * d);    
  • dictionary.h头文件里面的API
 //计算关键词的hash值
unsigned dictionary_hash(const char * key); 

//创建dictionary对象
dictionary * dictionary_new(int size);   

//删除dictionary对象
void dictionary_del(dictionary * vd);   

//获取dictionary对象的key值
char * dictionary_get(dictionary * d, const char * key, char * def); 

//设置dictionary对象的key值
int dictionary_set(dictionary * vd, const char * key, const char * val); 

//删除dictionary对象的key值
void dictionary_unset(dictionary * d, const char * key); 

//保存dictionary对象
void dictionary_dump(dictionary * d, FILE * out);    

四、 iniparser库C语言操作实例

1、config.ini

编写配置文件:

vim config.ini
[BASIC_INFO]
version                        = V1.1.1.1
user                           = yikou
number                         = 999


[FTP]
ftppath                        = /home/ftp
ftpuser                        = ftp
ftppass                        = 123456
port                           = 21


[NETWORK]
interface                      = eth1
dns1                           = 8.8.8.8
dns2                           = 8.8.8.8
subnet                         = 255.255.255.0
router                         = 192.168.3.1

2、读取配置参数

尝试编写iniparser程序对ini文件进行修改:

#include 
#include "iniparser.h"
#include "dictionary.h"

#define PATH "config.ini"

typedef unsigned char BYTE;
typedef unsigned char UINT8;
typedef unsigned char UCHAR;

typedef unsigned short int UINT16;
typedef unsigned long int UINT32;

struct device_cfg_s{
/*basicinfo*/ 
 char version[32];
 char user[32];
 int number;
/*ftp*/ 
 char ftppath[128];
 char ftpuser[32];
 char ftppass[32];
 UINT16 port;
/*network*/ 
 char interface[16];
 char dns1[32];   
 char dns2[32];   
 char subnet[32];   
 char router[32]; 
};

struct device_cfg_s devcfg;

int cfg_load(char *name)
{
    dictionary *ini= NULL;
    /* 解析dictionary对象并返回(分配内存)dictionary对象*/
    ini = iniparser_load(name);
    if( ini ==NULL)
    {
        printf("iniparser  failure\n");
        return -1;
    }

 /*basicinfo*/
 strcpy(devcfg.version,iniparser_getstring(ini, "BASIC_INFO:version", "v0.0.0.0"));
 strcpy(devcfg.user ,iniparser_getstring(ini, "BASIC_INFO:user", "yikou"));
 devcfg.number = iniparser_getint(ini, "BASIC_INFO:number", 666);

 /*ftp*/ 
 strcpy(devcfg.ftppath ,iniparser_getstring(ini, "FTP:ftppath", "/"));
 strcpy(devcfg.ftpuser ,iniparser_getstring(ini, "FTP:ftpuser", "ftp"));
 strcpy(devcfg.ftppass ,iniparser_getstring(ini, "FTP:ftppass", "123456"));
 devcfg.port = iniparser_getint(ini, "FTP:port", 21);

 
 /*network*/ 
 strcpy(devcfg.interface,iniparser_getstring(ini, "NETWORK:interface", "eth0"));
 strcpy(devcfg.dns1,iniparser_getstring(ini, "NETWORK:dns1", NULL));
 strcpy(devcfg.dns2 ,iniparser_getstring(ini, "NETWORK:dns2", NULL));
 strcpy(devcfg.subnet ,iniparser_getstring(ini, "NETWORK:subnet", "255.255.255.0"));
 strcpy(devcfg.router ,iniparser_getstring(ini, "NETWORK:router", "192.168.3.1"));
 
    /* 返回dictionary对象的section,key对应的字串值 */
    printf("version:%s\n",devcfg.version);
    printf("user:%s\n", devcfg.user);
    printf("number:%d\n",devcfg.number);
 
    printf("ftppath:%s\n", devcfg.ftppath);
    printf("ftpuser:%s\n",devcfg.ftpuser);
    printf("ftppass:%s\n", devcfg.ftppass);
    printf("port:%d\n",devcfg.port);
 
    printf("interface:%s\n", devcfg.interface);
    printf("dns1:%s\n",devcfg.dns1);
    printf("dns2:%s\n", devcfg.dns2);

    printf("subnet:%s\n",devcfg.subnet);
    printf("router:%s\n", devcfg.router);
    iniparser_freedict(ini);
}
int main (int argc, char **argv)
{
 cfg_load(PATH);
 //cfg_save_key(PATH,"BASIC_INFO","chnAddr","3501");
 //cfg_save_key(PATH,"BASIC_INFO","enddeviceNo","87564289");
    return 0;
}

可以看到最终值以配置文件中的为准。

如果配置文件没有配置参数则以iniparser_getxxxxx()中默认值为准。

3、保存配置信息到文件

为方便保存键值,彭老师封装了函数

int cfg_save_key(char *filename,char *section,char *key,char *value)
参数:
    filename  配置文件名
    section   节名字
    key       键
    value     值
int cfg_save_key(char *filename,char *section,char *key,char *value)
{
 FILE  *fp = NULL  ;
 dictionary *ini= NULL;

 char item[128]={0};

 
 /* 解析dictionary对象并返回(分配内存)dictionary对象*/
 ini = iniparser_load(filename);
 if( ini ==NULL)
 {
  printf("iniparser  failure\n");
  return -1;
 }

 sprintf(item,"%s:%s",section,key);
 
 /* 设置dictionary对象的某个section:key的值 */
 iniparser_set(ini, item, value);

 fp = fopen(filename, "w");
 if( fp == NULL ) {
  printf("stone:fopen error!\n");
  exit(-1);
 }

 /* 保存dictionary对象 */
 //   iniparser_dumpsection_ini(ini, "BASIC_INFO", fp);
 iniparser_dump_ini(ini, fp);
 fclose(fp);
 /* 释放dictionary对象(内存)*/
 iniparser_freedict(ini);

}

例如我们修改BASIC_INFO节的user的值为yikoupengnumber值为12345

 cfg_save_key(PATH,"BASIC_INFO","user","yikoupeng");
 cfg_save_key(PATH,"BASIC_INFO","number","12345");

执行结果:

嵌入式项目开发中,会有很多功能模块需要频繁修改参数,Linux下我们可以通过ini格式的文件保存配置信息。

本文通过开源库iniparser,详细讲解如何用C语言实现ini文件的参数解析和配置保存。

本文代码实例获取方式见文末。

一、ini文件

1 什么是 ini文件

  • INI(Initialization File)文件是一种简单直观的数据存储格式,常用于配置应用程序的初始化设置。这种文件通常包含若干个节(section)和键值对(key-value pairs)。INI文件的每一部分都是自描述性的,易于阅读和编辑,使得非程序员也能轻易理解并修改配置参数。
  • INI文件因其简单易用性而在许多编程语言中广泛应用,尤其是在Windows操作系统中,很多应用程序都采用INI文件作为配置文件。当然,随着XML、JSON等更丰富、更结构化的数据交换格式的普及,INI文件在现代应用程序中的使用相对减少,但在一些轻量级应用或对启动速度有较高要求的情况下,仍然是一种常见且实用的配置文件格式。

2 ini文件结构

  • 节(Section):INI文件中的各个部分通过方括号 [] 包裹的名称来定义,例如 **[Section1]**。每个节可以包含多个键值对。
  • 键值对(Key-Value Pairs):键和值之间用等号 = 分隔,如 key1=value1。键通常是描述性质的字符串,而值则可以是字符串、数字或其他类型的数据。
  • 注释:注释行以分号 ; 开始,直到行尾都被视为注释内容,不会被程序解析。
  • 多行值:某些INI解析器允许值跨越多行,通常通过在行尾添加反斜杠 \ 来延续到下一行

3 ini文件举例

;author yikoupeng

[BASIC_INFO]
version                = V1.1.1.1
user                   = yikou
number                 = 999


[FTP]
ftppath                = /home/ftp
ftpuser                = ftp
ftppass                = 123456
port                   = 21

......

其中:

  • 注释以分号(;)开头
  • [BASIC_INFO]、[FTP]就是组名,
  • 组成员有“version”........“ftppath”...

注意:

每个组下的key是唯一不能重复的,但不同组下可以存在相同的key.

二、 iniparser库

1. iniparser介绍

iniparser是一个C语言库,用于解析和操作 INI 格式的配置文件,是针对INI文件的开源解析器。

iniparser可以对配置文件进行解析、添加、修改、删除等操作。

git地址如下:

 https://github.com/ndevilla/iniparser

2. iniparser的安装

1、下载iniparser

wget https://codeload.github.com/ndevilla/iniparser/tar.gz/refs/tags/v4.1 -O iniparserv4.1.tar.gz

2、解压

tar -zxvf iniparserv4.1.tar.gz  

3、进入目录

cd iniparser-4.1/
peng@ubuntu:~/work/iniparser-4.1$ ls
AUTHORS  doc  example  FAQ-en.md  FAQ-zhcn.md  html  INSTALL  libiniparser.a  libiniparser.so.1  LICENSE  Makefile  README.md  src  test

4、进入src文件夹可以看到我们所需要的主要代码

peng@ubuntu:~/work/iniparser-4.1$ cd src/
peng@ubuntu:~/work/fdw/code/config/iniparser-4.1/src$ ls
dictionary.c  dictionary.h   iniparser.c  iniparser.h 

如果想移植该程序到我们的项目中,只需要将这几个文件添加到工程对应目录,编译进工程即可。

三、iniparser API(应用编程程序接口)

dictionary.h里面声明了一些直接解析ini file的API,iniparser.h头文件里面声明了一些提供用户操作的API。

iniparser.h里面的API是对dictionary.h里面API的再次封装,以提供用户友好性。

iniparser.h头文件里面的主要API

1 加载ini文件

/*
   *  @brief  从ini格式的配置文件中加载数据
   *  @param  [IN]  ininame  要打开的ini格式文件            
   *  @return != NULL 返回一个指向dictionary结构的指针
   *          == NULL 加载ini文件失败
  */
  dictionary * iniparser_load(const char *ininame);

2 获取键值

  • /*
    * @brief 获取指定键(key)对应的字符串类型的值
    * @param [IN] d dictionary结构的指针
    * @param [IN] key 要查找的键,通常格式为 "section:key",表示要获取哪个节(section)下的哪一项(key)的值。
    * @param [IN] def 当键不存在或者其值不是字符串时的默认返回值。如果没有找到对应键,函数将返回此默认值。
    * @return 如果找到了相应的键,返回键值对应字符串
    * 如果没有找到匹配的键,返回def指定的字符串值
    */

    const char * iniparser_getstring(const dictionary *d, const char *key, const char *def);

    /*
    * @brief 获取指定键(key)对应的整数值
    * @param [IN] d dictionary结构的指针
    * @param [IN] key 要查找的键,通常格式为 "section:key",表示要获取哪个节(section)下的哪一项(key)的值。
    * @param [IN] notfound 当键不存在或者其值不能被转换为整数时,函数将返回这个默认值。
    * @return 如果找到了相应的键,并且其值可以被成功转换为整数,则返回该整数值。
    * 如果没有找到匹配的键,或者该键对应的值无法转换为整数,则返回 notfound 参数提供的默认值。
    */

    int iniparser_getint(const dictionary * d, const char * key, int notfound);

    /*
    * @brief 获取指定键(key)对应的浮点型值
    * @param [IN] d dictionary结构的指针
    * @param [IN] key 要查找的键,通常格式为 "section:key",表示要获取哪个节(section)下的哪一项(key)的值。
    * @param [IN] notfound 当键不存在或者其值无法转换为双精度浮点数时,函数返回的默认值。
    * @return 如果找到了相应的键,并且其值能成功转换为一个双精度浮点数,则返回该浮点数。
    * 如果没有找到匹配的键,或者键的值不能被解释为一个有效的双精度浮点数,则返回 notfound 参数所提供的默认值。
    */

    double iniparser_getdouble(const dictionary *d, const char *key, double notfound);

3 设置键值

/*
  *  @brief  设置或修改 ini  配置文件中某个键值对
  *  @param  [IN]  d  dictionary结构的指针   
  *  @param  [IN]  entry  字符串形式的键值对标识符,格式通常是 "section:key",表明您要在哪个节(section)下的哪个键(key)上设置或修改值(val)。
  *      key值存在则修改对应val,key值不存在则会新增
  *  @param  [IN]  val: 要设置的新值,作为字符串传递。
  *  @return 返回0表示设置成功
  */
  int iniparser_set(dictionary *ini, const char *entry, const char *val);

4 移除键值

  • /*
    * @brief 移除 ini 配置文件中某个键值对
    * @param [IN] d dictionary结构的指针
    * @param [IN] entry 字符串形式的键名,包括可选的部分名称(section)和键(key)
    * 如果不指定key,则会移除整个section
    */

    void iniparser_unset(ini, const char *entry);

5 判断键是否存在

  • /*
    * @brief 判断 ini 配置文件是否存在某个键值
    * @param [IN] d dictionary结构的指针
    * @param [IN] entry 字符串形式的键值对标识符,格式通常是 "section:key"
    * @return 返回1表示存在,返回0表示不存在
    */

    int iniparser_find_entry(const dictionary *ini, const char *entry);

6 获取section个数

  • /*
    * @brief 获取ini配置文件中section的数量
    * @param [IN] d dictionary结构的指针
    * @return 成功返回section个数,失败返回 -1
    */

    int iniparser_getnsec(const dictionary * d);

    /*
    * @brief 获取某个section值
    * @param [IN] d dictionary结构的指针
    * @param [IN] n 指定获取第几个section值
    * @return 成功返回获取到的section值,失败返回NULL
    */

    const char *iniparser_getsecname(const dictionary * d, int n);

7 获取section下key个数

  • /*
    * @brief 获取ini配置文件中某个section的key个数
    * @param [IN] d dictionary结构的指针
    * @param [IN] s section
    * @return 返回指定section下的key个数
    */

    int iniparser_getsecnkeys(dictionary * d, char * s);

    /*
    * @brief 获取ini配置文件中某个section的所有key
    * @param [IN] d dictionary结构的指针
    * @param [IN] s section
    * @param [OUT] keys 通过这个参数输出key,也可以通过返回值获取
    * @return 成功返回指定section下的key,失败返回NULL
    */

    const char **iniparser_getseckeys(const dictionary *d, const char *s, const char **keys)

8 保存dictionary对象到文件中

  • /*
    * @brief 保存dictionary对象到文件中
    * @param [IN] d dictionary结构的指针
    * @param [IN] f 已打开的文件描述符
    */

    void iniparser_dump_ini(const dictionary *d, FILE *f);

9 释放dictionary对象

  • /*
    * @brief 释放dictionary对象
    * @param [IN] d dictionary结构的指针
    */

    void iniparser_freedict(dictionary * d);

10 api汇总

  • iniparser.h头文件里面的API
//获取dictionary对象的section个数  
int iniparser_getnsec(dictionary * d);  

 //获取dictionary对象的第n个section的名字  
char * iniparser_getsecname(dictionary * d, int n);

 //保存dictionary对象到file  
void iniparser_dump_ini(dictionary * d, FILE * f); 

 //保存dictionary对象一个section到file
void iniparser_dumpsection_ini(dictionary * d, char * s, FILE * f);  

 //保存dictionary对象到file 
void iniparser_dump(dictionary * d, FILE * f);  

//获取dictionary对象某个section下的key个数 
int iniparser_getsecnkeys(dictionary * d, char * s);  

//获取dictionary对象某个section下所有的key
char ** iniparser_getseckeys(dictionary * d, char * s);   

//返回dictionary对象的section:key对应的字串值  
char * iniparser_getstring(dictionary * d, const char * key, char * def); 

 //返回idictionary对象的section:key对应的整形值  
int iniparser_getint(dictionary * d, const char * key, int notfound); 

//返回dictionary对象的section:key对应的双浮点值  
double iniparser_getdouble(dictionary * d, const char * key, double notfound);  

 //返回dictionary对象的section:key对应的布尔值  
int iniparser_getboolean(dictionary * d, const char * key, int notfound);  

//设置dictionary对象的某个section:key的值  
int iniparser_set(dictionary * ini, const char * entry, const char * val); 

//删除dictionary对象中某个section:key
void iniparser_unset(dictionary * ini, const char * entry);  

//判断dictionary对象中是否存在某个section:key
int iniparser_find_entry(dictionary * ini, const char * entry) ;  

 //解析dictionary对象并返回(分配内存)dictionary对象
dictionary * iniparser_load(const char * ininame);

//释放dictionary对象(内存)  
void iniparser_freedict(dictionary * d);    
  • dictionary.h头文件里面的API
 //计算关键词的hash值
unsigned dictionary_hash(const char * key); 

//创建dictionary对象
dictionary * dictionary_new(int size);   

//删除dictionary对象
void dictionary_del(dictionary * vd);   

//获取dictionary对象的key值
char * dictionary_get(dictionary * d, const char * key, char * def); 

//设置dictionary对象的key值
int dictionary_set(dictionary * vd, const char * key, const char * val); 

//删除dictionary对象的key值
void dictionary_unset(dictionary * d, const char * key); 

//保存dictionary对象
void dictionary_dump(dictionary * d, FILE * out);    

四、 iniparser库C语言操作实例

1、config.ini

编写配置文件:

vim config.ini
[BASIC_INFO]
version                        = V1.1.1.1
user                           = yikou
number                         = 999


[FTP]
ftppath                        = /home/ftp
ftpuser                        = ftp
ftppass                        = 123456
port                           = 21


[NETWORK]
interface                      = eth1
dns1                           = 8.8.8.8
dns2                           = 8.8.8.8
subnet                         = 255.255.255.0
router                         = 192.168.3.1

2、读取配置参数

尝试编写iniparser程序对ini文件进行修改:

#include 
#include "iniparser.h"
#include "dictionary.h"

#define PATH "config.ini"

typedef unsigned char BYTE;
typedef unsigned char UINT8;
typedef unsigned char UCHAR;

typedef unsigned short int UINT16;
typedef unsigned long int UINT32;

struct device_cfg_s{
/*basicinfo*/ 
 char version[32];
 char user[32];
 int number;
/*ftp*/ 
 char ftppath[128];
 char ftpuser[32];
 char ftppass[32];
 UINT16 port;
/*network*/ 
 char interface[16];
 char dns1[32];   
 char dns2[32];   
 char subnet[32];   
 char router[32]; 
};

struct device_cfg_s devcfg;

int cfg_load(char *name)
{
    dictionary *ini= NULL;
    /* 解析dictionary对象并返回(分配内存)dictionary对象*/
    ini = iniparser_load(name);
    if( ini ==NULL)
    {
        printf("iniparser  failure\n");
        return -1;
    }

 /*basicinfo*/
 strcpy(devcfg.version,iniparser_getstring(ini, "BASIC_INFO:version", "v0.0.0.0"));
 strcpy(devcfg.user ,iniparser_getstring(ini, "BASIC_INFO:user", "yikou"));
 devcfg.number = iniparser_getint(ini, "BASIC_INFO:number", 666);

 /*ftp*/ 
 strcpy(devcfg.ftppath ,iniparser_getstring(ini, "FTP:ftppath", "/"));
 strcpy(devcfg.ftpuser ,iniparser_getstring(ini, "FTP:ftpuser", "ftp"));
 strcpy(devcfg.ftppass ,iniparser_getstring(ini, "FTP:ftppass", "123456"));
 devcfg.port = iniparser_getint(ini, "FTP:port", 21);

 
 /*network*/ 
 strcpy(devcfg.interface,iniparser_getstring(ini, "NETWORK:interface", "eth0"));
 strcpy(devcfg.dns1,iniparser_getstring(ini, "NETWORK:dns1", NULL));
 strcpy(devcfg.dns2 ,iniparser_getstring(ini, "NETWORK:dns2", NULL));
 strcpy(devcfg.subnet ,iniparser_getstring(ini, "NETWORK:subnet", "255.255.255.0"));
 strcpy(devcfg.router ,iniparser_getstring(ini, "NETWORK:router", "192.168.3.1"));
 
    /* 返回dictionary对象的section,key对应的字串值 */
    printf("version:%s\n",devcfg.version);
    printf("user:%s\n", devcfg.user);
    printf("number:%d\n",devcfg.number);
 
    printf("ftppath:%s\n", devcfg.ftppath);
    printf("ftpuser:%s\n",devcfg.ftpuser);
    printf("ftppass:%s\n", devcfg.ftppass);
    printf("port:%d\n",devcfg.port);
 
    printf("interface:%s\n", devcfg.interface);
    printf("dns1:%s\n",devcfg.dns1);
    printf("dns2:%s\n", devcfg.dns2);

    printf("subnet:%s\n",devcfg.subnet);
    printf("router:%s\n", devcfg.router);
    iniparser_freedict(ini);
}
int main (int argc, char **argv)
{
 cfg_load(PATH);
 //cfg_save_key(PATH,"BASIC_INFO","chnAddr","3501");
 //cfg_save_key(PATH,"BASIC_INFO","enddeviceNo","87564289");
    return 0;
}

可以看到最终值以配置文件中的为准。

如果配置文件没有配置参数则以iniparser_getxxxxx()中默认值为准。

3、保存配置信息到文件

为方便保存键值,彭老师封装了函数

int cfg_save_key(char *filename,char *section,char *key,char *value)
参数:
    filename  配置文件名
    section   节名字
    key       键
    value     值
int cfg_save_key(char *filename,char *section,char *key,char *value)
{
 FILE  *fp = NULL  ;
 dictionary *ini= NULL;

 char item[128]={0};

 
 /* 解析dictionary对象并返回(分配内存)dictionary对象*/
 ini = iniparser_load(filename);
 if( ini ==NULL)
 {
  printf("iniparser  failure\n");
  return -1;
 }

 sprintf(item,"%s:%s",section,key);
 
 /* 设置dictionary对象的某个section:key的值 */
 iniparser_set(ini, item, value);

 fp = fopen(filename, "w");
 if( fp == NULL ) {
  printf("stone:fopen error!\n");
  exit(-1);
 }

 /* 保存dictionary对象 */
 //   iniparser_dumpsection_ini(ini, "BASIC_INFO", fp);
 iniparser_dump_ini(ini, fp);
 fclose(fp);
 /* 释放dictionary对象(内存)*/
 iniparser_freedict(ini);

}

例如我们修改BASIC_INFO节的user的值为yikoupengnumber值为12345

 cfg_save_key(PATH,"BASIC_INFO","user","yikoupeng");
 cfg_save_key(PATH,"BASIC_INFO","number","12345");

执行结果:

可以看到配置文件basic_info节的usernumber 键值对被修改。

后台回复:iniparser

可以看到配置文件basic_info节的usernumber 键值对被修改。

后台回复:iniparser

相关推荐

ARM64内核内存布局图(ARM64内核内存布局图解)

ARM64架构处理器采用48位物理寻址机制,最大可以寻找到256TB的物理地址空间。对于目前的应用来说已经足够了,不需要扩展到64位的物理地址寻址。虚拟地址也同样最大支持48位支持,所以在处理器的架构...

ARM64 linux 调试串口通信(ARM64 linux 调试串口通信实验报告)

ARM64linux调试串口通信随着国产机普及很多工作也转移到了新平台上,以前调试设备用的笔记本电脑也换成新国产ARM64架构的了。本文以绿联CM204USB-A转RJ45Console调试线...

Gentoo Linux 终止对 Itanium IA-64 体系的支持

GentooLinux是最后几个继续维护Itanium(IA-64)架构构建的Linux发行版之一,但现在这些已停产的英特尔处理器正在逐步淘汰。由于Linux6.7内核放弃了对Itan...

如何检查 Linux 系统是 32 位还是 64 位?这9个命令查的又快又准!

在Linux系统中,位数(bit)通常指的是CPU架构的位宽,即CPU一次能够处理的数据量。32位系统和64位系统在内存寻址能力、计算性能和软件支持上存在显著差异:「32位系统」:...

调出好画面!带你玩转飞凌嵌入式AM62x开发板的显示接口

来源:飞凌嵌入式官网“显示”是嵌入式开发板最为重要的功能之一,能够支持更多种类、更高规格的显示接口,意味着它能够应对的使用场景也更加广泛。每一款嵌入式开发板在出厂前都会做屏幕调试,但在客户的实际项目开...

带你玩转AM62x开发板的显示接口——LVDS的显示和修改方式

此前小编已为大家介绍过OK6254-C开发板的RGB显示和修改方式,今天将继续为大家介绍OK6254-C开发板的LVDS显示和修改方式。话不多说,我们进入正题。1、LVDS接口规格飞凌嵌入式OK62...

AM335x继任者?AM6254性能解析(am2361p)

飞凌嵌入式FET6254-C核心板基于TISitaraTMAM62x系列工业级处理器设计开发,采用ARMCortex-A53架构,主频最高可达1.4GHz;并集成了丰富的接口,可广泛应用于的工...

如何在 Linux 发行版中安装微信和 QQ?

很多人因为工作沟通的原因需要用到微信和QQ,那么如何在Linux发行版中安装微信和QQ呢?以下是一些尝试的解决方法。QQ上一个版本的QQLinux版还是在2009年,而在现在,基于N...

MySQL:物理备份工具XBK(mysql 备份方案)

XBK的优缺点:XBK(PerconaXtraBackup)优点:1.免费2.热备:备份期间不阻塞innodb和XtraDB表,但会阻塞Myisam表3.物理备份:备份恢复快XBK缺点:1.不支持远...

AMD锐龙9 9950X CPU AIDA64跑分曝光:比7950X最高快45%

IT之家6月26日消息,Anandtech论坛网友igor_kavinski本周一发布帖子,分享了AMD旗舰锐龙99950X处理器的AIDA64基准测试跑分,与当前基于Z...

qemu linux内核(5.10.209)开发环境搭建

版本信息宿主机:ubuntu20.04.6LTS(FocalFossa)虚拟机:ubuntu20.04.6LTS(FocalFossa)安装宿主机的步骤省略,和一般的在vmware中安...

iPhone 7成刷机神器,成功运行乌班图、Linux、安卓

在智能机刚开始流行的时候,很多手机发烧友都喜欢刷机,当时民间大神们制作了特别多优化的ROM。后来随着手机硬件的逐步提升,以及厂商们对系统的大力优化,让大家对于刷机的兴趣也越来越少。不知道大家还记得这部...

12 款最佳免费开源 Linux 渲染器 | 火狐浏览器 130.0 版本更新

12款最佳免费开源Linux渲染器Linux的一大优势在于其拥有丰富的开源软件,可以满足艺术家、摄影师、动画师和设计师的需求。凭借价格低廉的硬件、免费的软件以及少量的才能和灵感,任何人都可以创...

Linux中xargs 命令详解与实用场景

xargs是Linux系统中常用的命令行工具之一,它能够从标准输入构造参数列表并传递给其他命令使用,是处理批量数据操作时的重要利器。一、xargs的基本语法xargs[OPTION]...[C...

Linux 磁盘扩容(非LVM)方式(linux扩容lvm磁盘容量)

今天接到一个客户的需求,CentOS的/分区容量太小了,OA系统所有的数据都在这下面,由于当时前同事给客户安装系统时采用了标准分区,而不是LVM逻辑卷,所以不支持在线扩容。df-hT查看磁盘使...