原地址: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. boost 分析命令行参数

    #include <boost/program_options.hpp> #include <iostream> #include <vector> using n ...

  2. GTest交流与经验总结

    GTest交流与经验总结 原文见:   http://starsourcingsolutions.com/myblog/?p=159

  3. Swift - 如何实现字符串的HMAC_SHA1加密

    前段时间有个网友问是否有Swift的HMAC_SHA1算法.这次就专门写篇相关文章进行介绍.要说明HMAC-SHA1,首先要先了解什么是HMAC,什么是SHA. 1,HMAC(散列消息身份验证码:Ha ...

  4. iOS - 单例传值 (一)

    点击打开链接    iOS - 单例传值 (二) 单例只会对某个类实例化一次/单例类,对单例这个类实例化一次有且仅有一个对象 你单例初始化,只能初始化一次,然后你指向的对象,其实都是指向一个内存地址, ...

  5. VIM IDE

    打造VIM IDE(针对C语言开发者)   ================================使用vim打造IDE, 针对C语言开发者建议使用gvim================== ...

  6. Ansi,UTF8,Unicode,ASCII编码的差别

    近日须要不同的编码,关于上述编码,一直迷迷糊糊,查了些资料,总算大致了解了,以下全是从网上搜来的: 1.  ASCII和Ansi编码    字符内码(charcter code)指的是用来代表字符的内 ...

  7. Exchange Server 2013传输规则之全新附件限制

  8. jsonp与cors跨域的一些理解

    浏览器的同源策略,即是浏览器之间要隔离不同域的内容,禁止互相操作. 比如,当你打开了多个网站,如果允许多个网站之间互相操作,那么其中一个木马网站就可以通过这种互相操作进行一系列的非法行为,获取你在各个 ...

  9. 高性能JavaScript模板引擎原理解析

    随着 web 发展,前端应用变得越来越复杂,基于后端的 javascript(Node.js) 也开始崭露头角,此时 javascript 被寄予了更大的期望,与此同时 javascript MVC ...

  10. 九度OnlineJudge之1018:统计同成绩学生人数

    题目描述: 读入N名学生的成绩,将获得某一给定分数的学生人数输出. 输入:                        测试输入包含若干测试用例,每个测试用例的格式为 第1行:N 第2行:N名学生的 ...