分享

INI配置文件解析C函数库

 quasiceo 2013-12-01
October 20, 2011 分类: ASM/C/C++     作者: hoverlees     留言: 13

ini是Windows上较常用的小型配置文件,并且windows api提供方便的函数供应用程序读写配置,可惜linux等其它操作系统上的需要用其它的方式.
我这儿写ini配置库是可以跨平台使用的,对于需要跨平台但使用相同配置的应用来说是个不错的选择.
支持符合windows ini标准的配置文件.
有趣兴的朋友可以拿去研究研究.

[2012-2-9日最新更新]

感谢前段时间一个网友提到程序的一些Bug,已修正程序,这次亲自在windows和linux下测试.已经支持GBK,UTF-8编码的ini文件解析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/**
 * INI配置文件管理函数库
 * Ini file parse functions.
 * By Hoverlees http://www. me[at]
 */
 
#ifndef _HOVERLEES_INI_CONFIG_H
#define _HOVERLEES_INI_CONFIG_H
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
//#include <unistd.h>
 
typedef struct _CONFIG_BTREE_NODE{
    char*   key;
    void*   data;
    struct _CONFIG_BTREE_NODE* left;
    struct _CONFIG_BTREE_NODE* right;
    char mem[2];
}CONFIG_BTREE_NODE;
 
typedef struct _CONFIG_BTREE{
    int numNodes;
    CONFIG_BTREE_NODE* root;
}CONFIG_BTREE;
 
typedef CONFIG_BTREE INI_CONFIG;
 
typedef int (*CONFIG_BTREE_TRAVERSE_CB)(CONFIG_BTREE_NODE* node);
typedef int (*CONFIG_BTREE_SAVE_TRAVERSE_CB)(FILE* fp,CONFIG_BTREE_NODE* node);
 
/**
 * ini内容解析函数,从字符串解析配置
 * @param str 字符串
 * @param slen 字符串长度,可以为0,如果为0,函数自动计算字符串长度
 * @param isGBK 如果ini文件使用GBK字符集,设置成1,否则设置成0
 * @return 成功返回INI_CONFIG指针,失败返回null
 */
INI_CONFIG* ini_config_create_from_string(unsigned char* str,int slen,int isGBK);
 
/**
 * ini内容解析函数,从文件解析配置
 * @param filename 配置文件名
 * @param isGBK 如果ini文件使用GBK字符集,设置成1,否则设置成0
 * @return 成功返回INI_CONFIG指针,失败返回null
 */
INI_CONFIG* ini_config_create_from_file(const char* filename,int isGBK);
 
/**
 * 配置释放函数,释放所占用的内存及数据结构
 * @param config 配置对象指针
 * @return 成功返回1,失败返回0
 */
void ini_config_destroy(INI_CONFIG* config);
/**
 * 获取配置整数值
 * @param config 配置对象指针
 * @param section 段名,没有段名时可以为NULL
 * @param key 键名
 * @param default_int 默认值
 * @return 如果配置中有此键对应的值,返回该值,否则返回参数指定的默认值
 */
int ini_config_get_int(INI_CONFIG* config,const char* section,const char* key,int default_int);
/**
 * 获取配置字符串值
 * @param config 配置对象指针
 * @param section 段名,没有段名时可以为NULL
 * @param key 键名
 * @param default_string 默认值
 * @return 如果配置中有此键对应的值,返回该值,否则返回参数指定的默认值
 */
char* ini_config_get_string(INI_CONFIG* config,const char* section,const char* key,char* default_string);
/**
 * 设置变量
 * @param config 配置对象指针
 * @param section 段名,没有段名时可以为NULL
 * @param key 键名
 * @param key_len 键长
 * @param value 值
 * @param value_len 值长度
 * @return 成功为1,失败为0
 */
int ini_config_set_string(INI_CONFIG* config,const char* section,const char* key,int key_len,const char* value,int value_len);
/**
 * 设置变量
 * @param config 配置对象指针
 * @param section 段名,没有段名时可以为NULL
 * @param key 键名
 * @param key_len 键长
 * @param value 整数值
 * @return 成功为1,失败为0
 */
int ini_config_set_int(INI_CONFIG* config,const char* section,const char* key,int key_len,int value);
/**
 * 保存配置到文件中 *提示,原先配置文件中的注释信息将不会保存.
 * @param config 配置对象指针
 * @param filename 保存到的文件
 * @return 成功为1,失败为0
 */
int ini_config_save(INI_CONFIG* config,const char* filename);
/**
 * 类似于ini_config_save,只是参数是文件指针,此函数可以直接使用stdin,stdout,stderr. *提示:本函数不负责关闭fp.
 * @param config 配置对象指针
 * @param fp 文件指针
 * @return 成功为1,失败为0
 */
int ini_config_print(INI_CONFIG* config,FILE* fp);
 
#endif

下面是调用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "confile.h"
 
void main(int argc,char* argv[]){
    INI_CONFIG* config;
    printf("------------test1-----------\n");
    config=ini_config_create_from_string("hover     =      lees       \n data =    7 \n maxthread=255\n;this is a comment line\r\nyahoo    =alibaba     \n     [section1]   \nhover   =  lees2  \nhover=lees333\n\n hover = lees4444\nyahoo=3\n\n\n",0,0);
    if(config){
        ini_config_print(config,stdout);
        ini_config_destroy(config);
    }
 
    printf("\n------------test2-----------\n");
    config=ini_config_create_from_file("php.ini",0);
    if(config){
        printf(
            "%s %s\n",
            ini_config_get_string(config,"soap","soap.wsdl_cache_dir","/nodir"),
            ini_config_get_string(config,"soap","soap.wsdl_cache_ttl","xixi")
        );
        ini_config_destroy(config);
    }
}

本例执行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
hover@hover-laptop:~/Desktop/c/inifile$ ./test
------------test1-----------
[default]
data=7
hover=lees
maxthread=255
yahoo=alibaba
[section1]
hover=lees4444
yahoo=3
 
------------test2-----------
2000 On

原代码在这里: 注意代码的编码是UTF-8的,因为本人在linux下开发的.如果要在windows下使用,请转换成GBK先.否则中文注释可能影响到代码.
confile.h confile.c

/**
* INI配置文件管理函数库
* Ini file parse functions.
* By Hoverlees http://www. me[at]
*/

#ifndef _HOVERLEES_INI_CONFIG_H
#define _HOVERLEES_INI_CONFIG_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
//#include <unistd.h>

typedef struct _CONFIG_BTREE_NODE{
char*    key;
void*    data;
struct _CONFIG_BTREE_NODE* left;
struct _CONFIG_BTREE_NODE* right;
char mem[2];
}CONFIG_BTREE_NODE;

typedef struct _CONFIG_BTREE{
int numNodes;
CONFIG_BTREE_NODE* root;
}CONFIG_BTREE;

typedef CONFIG_BTREE INI_CONFIG;

typedef int (*CONFIG_BTREE_TRAVERSE_CB)(CONFIG_BTREE_NODE* node);
typedef int (*CONFIG_BTREE_SAVE_TRAVERSE_CB)(FILE* fp,CONFIG_BTREE_NODE* node);

/**
* ini内容解析函数,从字符串解析配置
* @param str 字符串
* @param slen 字符串长度,可以为0,如果为0,函数自动计算字符串长度
* @param isGBK 如果ini文件使用GBK字符集,设置成1,否则设置成0
* @return 成功返回INI_CONFIG指针,失败返回null
*/
INI_CONFIG* ini_config_create_from_string(unsigned char* str,int slen,int isGBK);

/**
* ini内容解析函数,从文件解析配置
* @param filename 配置文件名
* @param isGBK 如果ini文件使用GBK字符集,设置成1,否则设置成0
* @return 成功返回INI_CONFIG指针,失败返回null
*/
INI_CONFIG* ini_config_create_from_file(const char* filename,int isGBK);

/**
* 配置释放函数,释放所占用的内存及数据结构
* @param config 配置对象指针
* @return 成功返回1,失败返回0
*/
void ini_config_destroy(INI_CONFIG* config);
/**
* 获取配置整数值
* @param config 配置对象指针
* @param section 段名,没有段名时可以为NULL
* @param key 键名
* @param default_int 默认值
* @return 如果配置中有此键对应的值,返回该值,否则返回参数指定的默认值
*/
int ini_config_get_int(INI_CONFIG* config,const char* section,const char* key,int default_int);
/**
* 获取配置字符串值
* @param config 配置对象指针
* @param section 段名,没有段名时可以为NULL
* @param key 键名
* @param default_string 默认值
* @return 如果配置中有此键对应的值,返回该值,否则返回参数指定的默认值
*/
char* ini_config_get_string(INI_CONFIG* config,const char* section,const char* key,char* default_string);
/**
* 设置变量
* @param config 配置对象指针
* @param section 段名,没有段名时可以为NULL
* @param key 键名
* @param key_len 键长
* @param value 值
* @param value_len 值长度
* @return 成功为1,失败为0
*/
int ini_config_set_string(INI_CONFIG* config,const char* section,const char* key,int key_len,const char* value,int value_len);
/**
* 设置变量
* @param config 配置对象指针
* @param section 段名,没有段名时可以为NULL
* @param key 键名
* @param key_len 键长
* @param value 整数值
* @return 成功为1,失败为0
*/
int ini_config_set_int(INI_CONFIG* config,const char* section,const char* key,int key_len,int value);
/**
* 保存配置到文件中 *提示,原先配置文件中的注释信息将不会保存.
* @param config 配置对象指针
* @param filename 保存到的文件
* @return 成功为1,失败为0
*/
int ini_config_save(INI_CONFIG* config,const char* filename);
/**
* 类似于ini_config_save,只是参数是文件指针,此函数可以直接使用stdin,stdout,stderr. *提示:本函数不负责关闭fp.
* @param config 配置对象指针
* @param fp 文件指针
* @return 成功为1,失败为0
*/
int ini_config_print(INI_CONFIG* config,FILE* fp);

#endif

标签: , ,
访客留言[谢谢!]
无名氏
呵呵,期待您的修正哦,看到您的代码受益匪浅,学习了。
2012-01-30 17:18:03
hoverlees
呵呵,谢谢夸奖.
2012-01-31 09:17:30
无名氏
ini文件中,有中文,会coredump
2012-01-30 15:09:38
hoverlees
对对,我当时没有考虑到,我有空去修正这个问题。谢谢朋友的指出。 如果朋友急着要使用这个库,可以在我的跳转函数中判断当前字节是否大于127,如果大于,则再读一个字节,并将这两个字节当成一个字符来处理(GBK), 如果第二个字节还是大于127,那么再读一个字节,并把这三个字节点一个字符处理(UTF-8),这样可以解决中文问题。
2012-01-30 16:06:08
Latrice
Superior tinhknig demonstrated above. Thanks!
2011-12-06 10:05:34
无名氏
可否愿意把您的QQ之类的联系方式发我邮箱吗,方便交流,也交个朋友
2012-01-31 11:38:35
无名氏
亲,有警告,不够完美。。
2013-05-09 18:45:55
无名氏
请问下你有没有能够根据关键字,来存储和取出多行数据的相关代码或者方法,有的话能发我邮箱一份吗?多谢
2013-05-06 10:01:04
hoverlees
你好,少量的你可以使用简单字符串搜索方法,如strstr,kmp,sunday等,大量的需要自己建立索引表,索引表的建立多种多样,这个关键就要看需求了。
2013-05-07 12:24:07
无名氏
请问有没有可以在windows系统下使用的头文件和源文件,能发我邮箱一份吗,有点急用,多谢!
2013-05-16 16:27:16
hoverlees
这份代码就可以直接在windows上编译。你也可以考虑直接用windows的ini的函数
2013-05-16 22:27:11
无名氏
使用这些函数,发现一个问题,往配置文件里存东西的时候,可能有多行,但是读取的时候只能读出一行数据,其他的读不出来,这个问题怎么解决?谢谢
2013-04-02 17:14:57
hoverlees
ini文件的规范也是不能使用多行作为值吧,至少我写的这个不能这样。 你可以自己加escape,如\n表示换行,\\表示原始\
2013-04-02 22:49:51

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多