原地址: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. 数据交换工具Kettle

    网上搜集了一些关于开源数据交换工具Kattle的文章,特收藏例如以下: 文章一:ETL和Kettle简单介绍 ETL即数据抽取(Extract).转换(Transform).装载(Load)的过程.它 ...

  2. python进阶十_正則表達式(一)

    近期状态一直不太好,至于原因,怎么说呢,不好说,总之就是纠结中覆盖着纠结,心思全然不在点上,希望能够借助Python的学习以及博客的撰写来调整回来,有的时候回头想一想,假设真的是我自己的问题呢,曾经我 ...

  3. Python基础入门教程

    Python基础入门教程 Python基础教程 Python 简介 Python环境搭建 Python 基础语法 Python 变量类型 Python 运算符 Python 条件语句 Python 循 ...

  4. SSH2三大框架整合警告

    *********************************************************************** * WARNING!!! * * * * >> ...

  5. 手把手教你安装QT集成开发环境(操作系统为ubuntu10.04)

    在安装QT集成开发工具包之前需要先安装build-essential和libncurses5-dev这两个开发工具和库,libncurses5-dev库是一个在Linux/Unix下广泛应用的图形函数 ...

  6. ActivityManager

    android.app.ActivityManager 这个类主要用来管理全部设备上的Activities. 权限:android.permission.GET_TASKS 方法:| 返回类型     ...

  7. 【linux】内核编译

    原创,转载时请注明,谢谢.邮箱:tangzhongp@163.com 博客园地址:http://www.cnblogs.com/embedded-tzp Csdn博客地址:http://blog.cs ...

  8. Tesseract Ocr引擎

    Tesseract Ocr引擎 1.Tesseract介绍 tesseract 是一个google支持的开源ocr项目,其项目地址:https://github.com/tesseract-ocr/t ...

  9. delpi中的RTTI初试

    java中的反射机制使我们能够在运行期间获取运行期类的信息,那么在delphi中有没有这样的功能呢?答案是有,实现这种功能的机制在delphi中叫做RTTI,废话少说,先来一段demo: 1.先定义一 ...

  10. 3篇OAuth的文章

    http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html http://blog.unvs.cn/archives/oauth-qq1.0-devel ...