原地址:http://blog.csdn.net/foruok/article/details/17715969

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

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

下面是头文件:

  1. #ifndef INI_PARSER_H
  2. #define INI_PARSER_H
  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif
  6. struct tag_value_list;
  7. struct ini_parser {
  8. struct tag_value_list * keyvalues;
  9. int (*parse_file)(struct ini_parser *, const char * file);
  10. int (*parse_string)(struct ini_parser *, const char *text);
  11. char * (*value)(struct ini_parser *, const char * key);
  12. void (*set_value)(struct ini_parser *, const char * key, const char * value);
  13. void (*remove)(struct ini_parser *, const char *key);
  14. int (*save_to_file)(struct ini_parser *, const char * file);
  15. };
  16. struct ini_parser * new_ini_parser();
  17. void delete_ini_parser(struct ini_parser *);
  18. #ifdef __cplusplus
  19. }
  20. #endif
  21. #endif // INI_PARSER_H

下面是源文件:

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

测试代码:

  1. #include "util/ini_parser.h"
  2. #include "ini_test.h"
  3. #include <stdio.h>
  4. #include <assert.h>
  5. static char * g_szIniString = "#abc\nfirst=2\nsecond\nname=charli  zhang \n";
  6. static void ini_parser_test_string()
  7. {
  8. struct ini_parser * ini = new_ini_parser();
  9. int size = ini->parse_string(ini, g_szIniString);
  10. assert( size > 0);
  11. assert( ini->value(ini, "second") == 0 );
  12. assert( ini->value(ini, "abc") == 0);
  13. assert( ini->value(ini, "name") != NULL );
  14. assert( ini->value(ini, "first") != NULL);
  15. printf("ini string: %s\n", g_szIniString);
  16. printf("key-value pairs count = %d\n", size);
  17. printf("key \'name\'', value = %s\n", ini->value(ini, "name"));
  18. printf("key \'first\'', value = %s\n", ini->value(ini, "first"));
  19. ini->set_value(ini, "baidu", "hahaha");
  20. ini->save_to_file(ini, "write.conf");
  21. ini->remove(ini, "first");
  22. ini->save_to_file(ini, "write2.conf");
  23. delete_ini_parser(ini);
  24. }
  25. static void ini_parser_test_file()
  26. {
  27. struct ini_parser * ini = new_ini_parser();
  28. int size = ini->parse_file(ini, "test.conf");
  29. assert( size > 0);
  30. assert( ini->value(ini, "second") == 0 );
  31. assert( ini->value(ini, "abc") == 0);
  32. assert( ini->value(ini, "name") != NULL );
  33. assert( ini->value(ini, "first") != NULL);
  34. printf("ini string: %s\n", g_szIniString);
  35. printf("key-value pairs count = %d\n", size);
  36. printf("key \'name\'', value = %s\n", ini->value(ini, "name"));
  37. printf("key \'first\'', value = %s\n", ini->value(ini, "first"));
  38. printf("key \'baidu\'', value = %s\n", ini->value(ini, "baidu"));
  39. delete_ini_parser(ini);
  40. }
  41. void ini_parser_test()
  42. {
  43. ini_parser_test_string();
  44. ini_parser_test_file();
  45. }

测试了解析字符串、文件、增、删、写文件,都没什么大问题。

纯C语言INI文件解析的更多相关文章

  1. ini文件解析c库(iniparser)

    一.交叉编译ini解析库 1.官方网站http://ndevilla.free.fr/iniparser 下载iniparser-3.1.tar.gz 2.解压 tar -zxvf iniparser ...

  2. ini文件解析c库(iniparser)【转】

    转自:http://www.cnblogs.com/dyllove98/archive/2013/07/28/3221732.html 一.交叉编译ini解析库 .官方网站http://ndevill ...

  3. 超赞的 Go 语言 INI 文件操作

    灵活的数据源 不光光可以从文件读取配置,还支持 []byte 类型的纯数据读取和基于 io.ReadCloser 的流式读取. 多种格式兼容 各种文件种类的广泛支持,包括但不限于 my.cnf..gi ...

  4. C++——INI文件详解

    原创声明:本文系博主原创文章,转载及引用请注明出处. 1. INI文件介绍 INI是英文单词 INItialization 的缩写,常作为Windows系统下的配置文件.INI文件是文本文件,通常用于 ...

  5. boost::property_tree读取解析ini文件--推荐

    boost::property_tree读取解析ini文件 #include "stdafx.h" #include <iostream> #include <b ...

  6. 实战parse_ini_file()及扩展函数解析ini文件完整版

    文章来源:PHP开发学习门户 地址:http://www.phpthinking.com/archives/587 在PHP站点开发的过程中,往往会用到读取ini參数配置文件,比方须要訪问一些复杂的借 ...

  7. python解析ini文件

    python解析ini文件 使用configparser - Configuration file parser sections() add_section(section) has_section ...

  8. 解决ini-parser解析ini文件中文乱码问题

    rickyah/ini-parser 是一个.net 平台解析ini文件的库,当ini文件中含有中文字符时会乱码. 解决:将文件通过Editplus 等文本编辑工具保存为 utf-8 + bom 格式 ...

  9. 【WPS】表格使用VBA宏编程写入ini文件实现软件多语言

    前言:公司软件最近在做多语言版本,而又来一个西班牙文版本的,之前已经做过中文版本,英文版本和法文版本,之前是同事做的,现在安排我做,之前的做法,使用wps表格,翻译好,然后一个一个复制粘贴到ini文件 ...

随机推荐

  1. hdu 4614 Vases and Flowers (二分 线段树)

    题目大意:爱丽丝有N个花瓶,每个花瓶最多放一朵花.然后又如下两个操作. 1:A B    从第A个花瓶开始,往后依次插B朵花,直到不能插为止.如果一朵花都不能插入就输出“can.....”,否则输出第 ...

  2. javascript操作元素的css样式

    我们经常要使用Javascript来改变页面元素的样式.当中一种办法是改变页面元素的CSS类(Class),这在传统的Javascript里,我们一般是通过处理HTML Dom的classname特性 ...

  3. JIRA初步

    JIRA 是澳大利亚 Atlassian 公司开发的一款优秀的问题跟踪管理软件工具.可以对各种类型的问题进行跟踪管理.包含缺陷.任务.需求.改进等.JIRA採用J2EE技术.可以跨平台部署.它正被广泛 ...

  4. 华为手机logcat不出日志解决方案

    解决方法:在拨打电话界面,录入*#*#2846579#*#* 自动进入开发界面菜单,进入第一个,选择开启logcat.

  5. sqlserver 存储过程实例

    ALTER PROC [dbo].[SP_mm_NS] (        @ID        NVARCHAR(60),        @ReturnCode    NVARCHAR(30) OUT ...

  6. 施用 maven shade plugin 解决 jar 或类的多版本冲突

    施用 maven shade plugin 解决 jar 或类的多版本冲突   使用 maven shade plugin 解决 jar 或类的多版本冲突java 应用经常会碰到的依赖的三方库出现版本 ...

  7. Linux 安装Redis全过程日志

    wget http://download.redis.io/redis-stable.tar.gz tar xvzf redis-stable.tar.gz cd redis-stable make ...

  8. http协议与web本质

    当你在浏览器地址栏敲入“http://www.csdn.net/”,然后猛按回车,呈现在你面前的,将是csdn的首页了(这真是废话,你会认为这是理所当然的).作为一个开发者,尤其是web开发人员,我想 ...

  9. Tomcat详细用法学习(五)

    本篇接上一篇<Tomcat详细用法学习(四)>,主要讲解Tomcat服务器的管理平台 我们可能会将很多web应用交给Tomcat,那么Tomcat服务器就要对我们这些载入的web应用进行管 ...

  10. 几十篇GDI以及MFC自绘的文章

    http://www.cnblogs.com/lidabo/category/434801.html