原地址: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. P65

    #include<stdio.h> #define N 6 main() { char c[N]; int i=0; for(;i<N;c[i]=getchar(),i++); pr ...

  2. CodeFirst 表之间的关联

    多重性关系可以是Optional(一个属性可拥有一个单个实例或没有) Required(一个属性必须拥有一个单个实例) Many很多的(一个属性可以拥有一个集合或一个单个实例). Has方法包括如下几 ...

  3. android studio 怎么运行java

    方法/步骤 1.新建一个project,或者如果已经有project的话,那就直接新建一个module.注意选择Java library,然后下一步 2.输入module的一些信息.点击finish ...

  4. 基于visual Studio2013解决面试题之1105字符串压缩

     题目

  5. Hadoop学习之HBase

    1. HBase有哪些基本的特征? 2. HBase相对于关系数据库能解决的问题是什么? 3. HBase的数据模型是什么?如何表述?有哪些操作形式? 4. HBase的模式Schema设计的一些概念 ...

  6. (转载)Jvm工作原理学习笔记

    一.        JVM的生命周期 1.      JVM实例相应了一个独立执行的java程序它是进程级别 a)    启动.启动一个Java程序时.一个JVM实例就产生了.不论什么一个拥有publ ...

  7. 6.MIL采集和实时显示

    前面讲到的都是离线的图像获取方法,实际中我们做机器视觉都是在线采集图像和处理,处理结果决定了计算机要给出的控制信号如电机运动等,这样就实现了实时视觉反馈运动.MIL中的采集需要Matrox采集板卡的支 ...

  8. Linux路由器

    Linux路由器 武溪嵌人 钻研嵌入式,改变未来 http://blog.csdn.net/zhang_danf     Linux路由器 http://blog.csdn.net/zhang_dan ...

  9. Android学习之一:Cygwin简介

    为了能够一窥Android底层的东东,还是要搭建编译Android的环境.虽有Ubuntu和Suse系统,无奈总感觉在不同的系统下切来切去很是不便.在Windows工作学习,要编译Android,就不 ...

  10. delphi中左右翻转窗体(修改EXStyle)

    unit Unit1; interface uses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Form ...