纯C语言INI文件解析

在一个跨平台( Android 、Windows、Linux )项目中配置文件用 INI 格式,自己写了个解析库,纯C语言的,简单好用。

    可以解析 INI 格式的字符串、解析文件、保存到文件。

    下面是头文件:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #ifndef INI_PARSER_H  
  2. #define INI_PARSER_H  
  3. #ifdef __cplusplus  
  4. extern "C" {  
  5. #endif  
  6. struct tag_value_list;  
  7.   
  8. struct ini_parser {  
  9.     struct tag_value_list * keyvalues;  
  10.     int (*parse_file)(struct ini_parser *, const char * file);  
  11.     int (*parse_string)(struct ini_parser *, const char *text);  
  12.     char * (*value)(struct ini_parser *, const char * key);  
  13.     void (*set_value)(struct ini_parser *, const char * key, const char * value);  
  14.     void (*remove)(struct ini_parser *, const char *key);  
  15.     int (*save_to_file)(struct ini_parser *, const char * file);  
  16. };  
  17.   
  18. struct ini_parser * new_ini_parser();  
  19. void delete_ini_parser(struct ini_parser *);  
  20.   
  21. #ifdef __cplusplus  
  22. }  
  23. #endif  
  24. #endif // INI_PARSER_H  

    下面是源文件:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include "ini_parser.h"  
  2. #include <stdio.h>  
  3. #include <string.h>  
  4. #include "tag_value.h"  
  5.   
  6. static struct tag_value_pair * parse_line(char *line, int len)  
  7. {  
  8.     struct tag_value_pair * pair = 0;  
  9.     int count = 0;  
  10.     char * p = line;  
  11.     char * end = 0;  
  12.     char * start = line;  
  13.     if(!p) return 0;  
  14.     while(*p == ' ') p++;  
  15.   
  16.   
  17.     /*blank line*/  
  18.     if(p - line == len ||  
  19.             *p == '\r' ||  
  20.             *p == '\n' ||  
  21.             *p == '\0'return 0;  
  22.   
  23.     /*do not support group*/  
  24.     if(*p == '['return 0;  
  25.     /*comments*/  
  26.     if(*p == '#'return 0;  
  27.   
  28.     /* extract key */  
  29.     start = p;  
  30.     end = line + len;  
  31.     while(*p != '=' && p!= end) p++;  
  32.     if(p == end)  
  33.     {  
  34.         /* none '=' , invalid line */  
  35.         return 0;  
  36.     }  
  37.     end = p - 1;  
  38.     while(*end == ' ') end--; /* skip blank at the end */  
  39.     count = end - start + 1;  
  40.   
  41.     pair = new_tag_value_pair();  
  42.     pair->szTag = malloc(count + 1);  
  43.     strncpy(pair->szTag, start, count);  
  44.     pair->szTag[count] = 0;  
  45.   
  46.     /* extract value */  
  47.     p++;  
  48.     end = line + len; /* next pos of the last char */  
  49.     while( *p == ' ' && p != end) p++;  
  50.     if(p == end)  
  51.     {  
  52.         delete_tag_value_pair(pair);  
  53.         return 0;  
  54.     }  
  55.     start = p;  
  56.     end--; /* to the last char */  
  57.     if(*end == '\n') { *end = 0; end--; }  
  58.     if(*end == '\r') { *end = 0; end--; }  
  59.     count = end - start + 1;  
  60.     if(count > 0)  
  61.     {  
  62.         pair->szValue = malloc(count + 1);  
  63.         strncpy(pair->szValue, start, count);  
  64.         pair->szValue[count] = 0;  
  65.     }  
  66.   
  67.     /* release empty key-value pair */  
  68.     if(!pair->szValue)  
  69.     {  
  70.         delete_tag_value_pair(pair);  
  71.         return 0;  
  72.     }  
  73.   
  74.     return pair;  
  75. }  
  76.   
  77. static int _parse_file(struct ini_parser * ini, const char *file){  
  78.     FILE * fp = fopen(file, "r");  
  79.     if(fp)  
  80.     {  
  81.         struct tag_value_pair * pair = 0;  
  82.         char buf[1024] = {0};  
  83.         while(fgets(buf, 1024, fp))  
  84.         {  
  85.             pair = parse_line(buf, strlen(buf));  
  86.             if(pair)  
  87.             {  
  88.                 ini->keyvalues->add(ini->keyvalues, pair);  
  89.             }  
  90.         }  
  91.         fclose(fp);  
  92.         return ini->keyvalues->size;  
  93.     }  
  94.     return -1;  
  95. }  
  96.   
  97. static int _parse_text(struct ini_parser * ini, const char * text){  
  98.     char *p = text;  
  99.     char * start = 0;  
  100.     struct tag_value_pair * pair = 0;  
  101.     if(!text) return -1;  
  102.   
  103.     while(1)  
  104.     {  
  105.         start = p;  
  106.         while(*p != '\n' && *p != '\0' )p++;  
  107.         if(*p == '\0'break;  
  108.   
  109.         pair = parse_line(start, p - start);  
  110.         if(pair) ini->keyvalues->add(ini->keyvalues, pair);  
  111.   
  112.         p++;  
  113.     }  
  114.   
  115.     return ini->keyvalues->size;  
  116. }  
  117.   
  118. static char * _value(struct ini_parser * ini, const char * key){  
  119.     struct tag_value_pair * pair = ini->keyvalues->find_by_tag(ini->keyvalues, key);  
  120.     if(pair) return pair->szValue;  
  121.     return 0;  
  122. }  
  123.   
  124. static void _set_value(struct ini_parser * ini, const char * key, const char *value){  
  125.     struct tag_value_pair * pair = ini->keyvalues->find_by_tag(ini->keyvalues, key);  
  126.     if(pair)  
  127.     {  
  128.         if(pair->szValue) free(pair->szValue);  
  129.         pair->szValue = strdup(value);  
  130.     }  
  131.     else  
  132.     {  
  133.         ini->keyvalues->add(ini->keyvalues, make_tag_value_pair(key, value));  
  134.     }  
  135. }  
  136.   
  137. static void _remove(struct ini_parser * ini, const char * key){  
  138.     struct tag_value_pair * pair = ini->keyvalues->find_by_tag(ini->keyvalues, key);  
  139.     if(pair)ini->keyvalues->remove(ini->keyvalues, pair);  
  140. }  
  141.   
  142. static void write_keyvalue(struct tag_value_pair * pair, FILE *fp)  
  143. {  
  144.     fputs(pair->szTag, fp);  
  145.     fputc('=', fp);  
  146.     fputs(pair->szValue, fp);  
  147.     fputc('\n', fp);  
  148. }  
  149.   
  150. static int _save_to_file(struct ini_parser * ini, const char * file){  
  151.     if(ini->keyvalues->size > 0)  
  152.     {  
  153.         FILE * fp = fopen(file, "w");  
  154.         if(fp)  
  155.         {  
  156.             struct tag_value_pair * pair = ini->keyvalues->head;  
  157.             while(pair != ini->keyvalues->tail)  
  158.             {  
  159.                 write_keyvalue(pair, fp);  
  160.                 pair = pair->next;  
  161.             }  
  162.   
  163.             if(pair)write_keyvalue(pair, fp);  
  164.   
  165.             fclose(fp);  
  166.             return 0;  
  167.         }  
  168.     }  
  169.     return -1;  
  170. }  
  171.   
  172. struct ini_parser * new_ini_parser(){  
  173.     struct ini_parser * ini = (struct ini_parser*)malloc(sizeof(struct ini_parser));  
  174.     ini->keyvalues = new_tag_value_list();  
  175.     ini->parse_file = _parse_file;  
  176.     ini->parse_string = _parse_text;  
  177.     ini->value = _value;  
  178.     ini->set_value = _set_value;  
  179.     ini->remove = _remove;  
  180.     ini->save_to_file = _save_to_file;  
  181.     return ini;  
  182. }  
  183.   
  184. void delete_ini_parser(struct ini_parser *ini){  
  185.     if(ini)  
  186.     {  
  187.         delete_tag_value_list(ini->keyvalues);  
  188.         free(ini);  
  189.     }  
  190. }  

    测试代码:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include "util/ini_parser.h"  
  2. #include "ini_test.h"  
  3. #include <stdio.h>  
  4. #include <assert.h>  
  5.   
  6. static char * g_szIniString = "#abc\nfirst=2\nsecond\nname=charli  zhang \n";  
  7.   
  8. static void ini_parser_test_string()  
  9. {  
  10.     struct ini_parser * ini = new_ini_parser();  
  11.     int size = ini->parse_string(ini, g_szIniString);  
  12.   
  13.     assert( size > 0);  
  14.     assert( ini->value(ini, "second") == 0 );  
  15.     assert( ini->value(ini, "abc") == 0);  
  16.     assert( ini->value(ini, "name") != NULL );  
  17.     assert( ini->value(ini, "first") != NULL);  
  18.   
  19.     printf("ini string: %s\n", g_szIniString);  
  20.     printf("key-value pairs count = %d\n", size);  
  21.     printf("key \'name\'', value = %s\n", ini->value(ini, "name"));  
  22.     printf("key \'first\'', value = %s\n", ini->value(ini, "first"));  
  23.   
  24.     ini->set_value(ini, "baidu""hahaha");  
  25.     ini->save_to_file(ini, "write.conf");  
  26.   
  27.     ini->remove(ini, "first");  
  28.     ini->save_to_file(ini, "write2.conf");  
  29.   
  30.     delete_ini_parser(ini);  
  31. }  
  32.   
  33. static void ini_parser_test_file()  
  34. {  
  35.     struct ini_parser * ini = new_ini_parser();  
  36.     int size = ini->parse_file(ini, "test.conf");  
  37.   
  38.     assert( size > 0);  
  39.     assert( ini->value(ini, "second") == 0 );  
  40.     assert( ini->value(ini, "abc") == 0);  
  41.     assert( ini->value(ini, "name") != NULL );  
  42.     assert( ini->value(ini, "first") != NULL);  
  43.   
  44.     printf("ini string: %s\n", g_szIniString);  
  45.     printf("key-value pairs count = %d\n", size);  
  46.     printf("key \'name\'', value = %s\n", ini->value(ini, "name"));  
  47.     printf("key \'first\'', value = %s\n", ini->value(ini, "first"));  
  48.     printf("key \'baidu\'', value = %s\n", ini->value(ini, "baidu"));  
  49.   
  50.     delete_ini_parser(ini);  
  51. }  
  52.   
  53. void ini_parser_test()  
  54. {  
  55.     ini_parser_test_string();  
  56.     ini_parser_test_file();  
  57. }  

    测试了解析字符串、文件、增、删、写文件,都没什么大问题。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
c读写ini配置文件 用c/c++读写ini配置文件有不少第三方的开源库,如iniparser、libini、rwini、UltraLightINIParser等,但都不理想,往往代码较大、功能较弱、 接口使用不方便。尤其在大小写处理、前后空格、各种注释、跨平台换行符支持、带引号字符串处理、无section操作、原格式保持等方面存在问题。 现将本人精心制作的ini读写程序源码奉献给大家,c编写,简洁好用。支持windowslinux。 主要特点: 1、支持;和#注释符号,支持行尾注释。 2、支持带引号'或"成对匹配的字符串,提取时自动去引号。引号可带其它引号或;#注释符。 3、支持无section或空section(名称为空)。 4、支持10、16、8进制数,0x开头为16进制数,0开头为8进制。 5、支持section、key或=号前后带空格。 6、支持\n、\r、\r\n或\n\r换行格式。 7、不区分section、key大小写,但写入时以新串为准,并保持其大小写。 8、新增数据时,若section存在则在该节最后一个有效数据后添加,否则在文件尾部添加。 9、支持指定key所在整行删除,即删除该键值,包括注释。 10、可自动跳过格式错误行,修改时仍然保留。 11、修改时保留原注释:包括整行注释、行尾注释(包括前面空格)。 12、修改时保留原空行。以上三点主要是尽量保留原格式。 不足之处: 1、不支持单key多value(逗号分割),只能一次性提取后自行处理。 2、不支持同名重复section和key。(重复section可视为错误,重复key则可能造成分歧) 3、不能提取所有section或key名称。 使用只需两个文件inirw.h、inirw.c,另有测试程序和工程文件,支持windowslinux
C语言可以通过使用文件操作函数来读写INI文件INI文件是一种以文本形式存储配置信息的文件,包含一系列的节和键值对。下面是一个简单的示例: 首先,我们需要创建一个INI文件,并写入一些配置信息。 #include <stdio.h> int main() { // 打开INI文件 FILE *file = fopen("config.ini", "w"); if (file == NULL) { printf("无法打开INI文件。\n"); return 1; } // 写入配置信息 fprintf(file, "[System]\n"); fprintf(file, "Version=1.0\n"); fprintf(file, "Author=John Doe\n\n"); fprintf(file, "[Database]\n"); fprintf(file, "Host=localhost\n"); fprintf(file, "Port=3306\n"); fprintf(file, "Username=root\n"); fprintf(file, "Password=123456\n"); // 关闭INI文件 fclose(file); return 0; } 上述代码通过fopen函数创建一个名为config.iniINI文件,并使用fprintf函数写入了一些配置信息,每个节和键值对都以特定的格式写入。写入完成后,可以使用fclose函数关闭文件。 接下来,我们可以通过打开已有的INI文件来读取其的配置信息。 #include <stdio.h> #include <stdlib.h> int main() { // 打开INI文件 FILE *file = fopen("config.ini", "r"); if (file == NULL) { printf("无法打开INI文件。\n"); return 1; } char line[100]; char section[100]; char key[100]; char value[100]; // 逐行读取INI文件 while (fgets(line, sizeof(line), file) != NULL) { // 解析节 if (line[0] == '[' && line[strlen(line) - 2] == ']') { strncpy(section, line + 1, strlen(line) - 3); section[strlen(line) - 3] = '\0'; } // 解析键和值 else if (sscanf(line, "%[^=]=%[^\n]", key, value) == 2) { printf("节: %s, 键: %s, 值: %s\n", section, key, value); } } // 关闭INI文件 fclose(file); return 0; } 上述代码通过fopen函数打开了名为config.iniINI文件,并使用fgets函数以行为单位读取文件内容。然后,代码解析了每一行的内容,并将解析的结果输出。 这只是一个简单的示例,实际的INI文件读写可能会更加复杂。C语言提供了多种文件操作函数,可以进行更高级的INI文件读写操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值