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

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

下面是头文件:

#ifndef INI_PARSER_H
#define INI_PARSER_H
#ifdef __cplusplus
extern "C" {
#endif
struct tag_value_list;struct ini_parser {struct tag_value_list * keyvalues;int (*parse_file)(struct ini_parser *, const char * file);int (*parse_string)(struct ini_parser *, const char *text);char * (*value)(struct ini_parser *, const char * key);void (*set_value)(struct ini_parser *, const char * key, const char * value);void (*remove)(struct ini_parser *, const char *key);int (*save_to_file)(struct ini_parser *, const char * file);
};struct ini_parser * new_ini_parser();
void delete_ini_parser(struct ini_parser *);#ifdef __cplusplus
}
#endif
#endif // INI_PARSER_H

下面是源文件:

#include "ini_parser.h"
#include <stdio.h>
#include <string.h>
#include "tag_value.h"static struct tag_value_pair * parse_line(char *line, int len)
{struct tag_value_pair * pair = 0;int count = 0;char * p = line;char * end = 0;char * start = line;if(!p) return 0;while(*p == ' ') p++;/*blank line*/if(p - line == len ||*p == '\r' ||*p == '\n' ||*p == '\0') return 0;/*do not support group*/if(*p == '[') return 0;/*comments*/if(*p == '#') return 0;/* extract key */start = p;end = line + len;while(*p != '=' && p!= end) p++;if(p == end){/* none '=' , invalid line */return 0;}end = p - 1;while(*end == ' ') end--; /* skip blank at the end */count = end - start + 1;pair = new_tag_value_pair();pair->szTag = malloc(count + 1);strncpy(pair->szTag, start, count);pair->szTag[count] = 0;/* extract value */p++;end = line + len; /* next pos of the last char */while( *p == ' ' && p != end) p++;if(p == end){delete_tag_value_pair(pair);return 0;}start = p;end--; /* to the last char */if(*end == '\n') { *end = 0; end--; }if(*end == '\r') { *end = 0; end--; }count = end - start + 1;if(count > 0){pair->szValue = malloc(count + 1);strncpy(pair->szValue, start, count);pair->szValue[count] = 0;}/* release empty key-value pair */if(!pair->szValue){delete_tag_value_pair(pair);return 0;}return pair;
}static int _parse_file(struct ini_parser * ini, const char *file){FILE * fp = fopen(file, "r");if(fp){struct tag_value_pair * pair = 0;char buf[1024] = {0};while(fgets(buf, 1024, fp)){pair = parse_line(buf, strlen(buf));if(pair){ini->keyvalues->add(ini->keyvalues, pair);}}fclose(fp);return ini->keyvalues->size;}return -1;
}static int _parse_text(struct ini_parser * ini, const char * text){char *p = text;char * start = 0;struct tag_value_pair * pair = 0;if(!text) return -1;while(1){start = p;while(*p != '\n' && *p != '\0' )p++;if(*p == '\0') break;pair = parse_line(start, p - start);if(pair) ini->keyvalues->add(ini->keyvalues, pair);p++;}return ini->keyvalues->size;
}static char * _value(struct ini_parser * ini, const char * key){struct tag_value_pair * pair = ini->keyvalues->find_by_tag(ini->keyvalues, key);if(pair) return pair->szValue;return 0;
}static void _set_value(struct ini_parser * ini, const char * key, const char *value){struct tag_value_pair * pair = ini->keyvalues->find_by_tag(ini->keyvalues, key);if(pair){if(pair->szValue) free(pair->szValue);pair->szValue = strdup(value);}else{ini->keyvalues->add(ini->keyvalues, make_tag_value_pair(key, value));}
}static void _remove(struct ini_parser * ini, const char * key){struct tag_value_pair * pair = ini->keyvalues->find_by_tag(ini->keyvalues, key);if(pair)ini->keyvalues->remove(ini->keyvalues, pair);
}static void write_keyvalue(struct tag_value_pair * pair, FILE *fp)
{fputs(pair->szTag, fp);fputc('=', fp);fputs(pair->szValue, fp);fputc('\n', fp);
}static int _save_to_file(struct ini_parser * ini, const char * file){if(ini->keyvalues->size > 0){FILE * fp = fopen(file, "w");if(fp){struct tag_value_pair * pair = ini->keyvalues->head;while(pair != ini->keyvalues->tail){write_keyvalue(pair, fp);pair = pair->next;}if(pair)write_keyvalue(pair, fp);fclose(fp);return 0;}}return -1;
}struct ini_parser * new_ini_parser(){struct ini_parser * ini = (struct ini_parser*)malloc(sizeof(struct ini_parser));ini->keyvalues = new_tag_value_list();ini->parse_file = _parse_file;ini->parse_string = _parse_text;ini->value = _value;ini->set_value = _set_value;ini->remove = _remove;ini->save_to_file = _save_to_file;return ini;
}void delete_ini_parser(struct ini_parser *ini){if(ini){delete_tag_value_list(ini->keyvalues);free(ini);}
}

测试代码:

#include "util/ini_parser.h"
#include "ini_test.h"
#include <stdio.h>
#include <assert.h>static char * g_szIniString = "#abc\nfirst=2\nsecond\nname=charli  zhang \n";static void ini_parser_test_string()
{struct ini_parser * ini = new_ini_parser();int size = ini->parse_string(ini, g_szIniString);assert( size > 0);assert( ini->value(ini, "second") == 0 );assert( ini->value(ini, "abc") == 0);assert( ini->value(ini, "name") != NULL );assert( ini->value(ini, "first") != NULL);printf("ini string: %s\n", g_szIniString);printf("key-value pairs count = %d\n", size);printf("key \'name\'', value = %s\n", ini->value(ini, "name"));printf("key \'first\'', value = %s\n", ini->value(ini, "first"));ini->set_value(ini, "baidu", "hahaha");ini->save_to_file(ini, "write.conf");ini->remove(ini, "first");ini->save_to_file(ini, "write2.conf");delete_ini_parser(ini);
}static void ini_parser_test_file()
{struct ini_parser * ini = new_ini_parser();int size = ini->parse_file(ini, "test.conf");assert( size > 0);assert( ini->value(ini, "second") == 0 );assert( ini->value(ini, "abc") == 0);assert( ini->value(ini, "name") != NULL );assert( ini->value(ini, "first") != NULL);printf("ini string: %s\n", g_szIniString);printf("key-value pairs count = %d\n", size);printf("key \'name\'', value = %s\n", ini->value(ini, "name"));printf("key \'first\'', value = %s\n", ini->value(ini, "first"));printf("key \'baidu\'', value = %s\n", ini->value(ini, "baidu"));delete_ini_parser(ini);
}void ini_parser_test()
{ini_parser_test_string();ini_parser_test_file();
}

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

纯C语言INI文件解析相关推荐

  1. c读取ini配置文件_Go-INI - 超赞的Go语言INI文件操作库

    INI 文件(Initialization File)是十分常用的配置文件格式,其由节(section).键(key)和值(value)组成,编写方便,表达性强,并能实现基本的配置分组功能,被各类软件 ...

  2. go 默认http版本_【每日一库】超赞的 Go 语言 INI 文件操作

    点击上方蓝色"Go语言中文网"关注我们,领全套Go资料,每天学习 Go 语言 如果你使用 INI 作为系统的配置文件,那么一定会使用这个库吧.没错,它就是号称地表 最强大.最方便  ...

  3. linux读ini文件,Linux下INI文件解析

    一个linux下的ini文件解析模块. 因为工作需要, 需要在linux环境去解析ini配置文件. 个人写了一个委简单ini解析模块. 先记录下ini文件的格式 ini文件的格式为 [section1 ...

  4. INI文件解析、遍历

    工作中时常需要给软件添加配置文件功能,INI文件简单又高效,但是微软的那套API使用太不方便,尤其是INI文件的遍历,所有花了一下午时间造了个轮子,自己解析INI文件. 目前只能读取Unicode小端 ...

  5. 纯perl语言计算文件的crc32值

    perl语言有次强大的正则表达式功能,因而我喜欢使用perl语言进行一些数据分析,在项目中也需要生成文件的crc值,在网上很多都是引用第三方的库进行计算,crc计算是使用位计算得来,因此可以通过纯pe ...

  6. 怎么把html转为ini,ini文件读写

    android编程ini文件读写 写了个android程序,想借助ini文件保存程序配置,供下次启动读取用,单android编程iniini文件读写的方法为: 一.将信息写入.INI文件中 1.所用的 ...

  7. 语言 读ini文件_让C语言的调试更加高大上

    一般在写一个项目的时候,为了更直观的调试,我们在程序里都会打printf调试语句,随着项目越写越多,printf也会越来越多,但项目准备结尾的时候,这时候开始优化就会发现,你想完全把printf语句都 ...

  8. INI文件快速解析java工具包

    FastIni 概述 相信大家都用过阿里的fastjson,它可以通过模板快速解析json字符串,也可以通过key快速获取json字符串中的值.通过模板类型快速解析json字符串是一个很好的想法,所以 ...

  9. boost::program_options模块一个配置ini文件被解析程序选项库,它包括许多不同的值类型的测试程序

    boost::program_options模块一个配置ini文件被解析程序选项库,它包括许多不同的值类型的测试程序 实现功能 C++实现代码 实现功能 boost::program_options模 ...

最新文章

  1. golang源码分析:调度器chan调度
  2. Json解析不允许子类父类变量重名的原因
  3. 编译Android VNC Server
  4. 曲奇饼案例运营管理_昆仑海岸 农村生活污水处理设施智慧运营管理项目荣获典型案例奖...
  5. Meaven的pom文件配置
  6. antd 3升级命令_是时候拥有一个你自己的命令行工具了
  7. 创意合成广告欣赏:让人脑洞大开的设计
  8. 使用Java快速实现进度条
  9. 中班机器人歌曲_幼儿园机器人教案音乐
  10. 山东省软件设计大赛参赛心得
  11. 利用FPGA实现简单的CPU
  12. 怎么生成自动参考文献(简单 有图)
  13. 杜邦分析法拆解三种商业模式
  14. RetinaFace人脸检测使用
  15. 如何实现自定义串口通信协议?
  16. 2014年双11抢货宝典-双11促销商品价格对比清单---妈妈再也不用担心我成为剁手党啦
  17. 罗素:自由主义的十诫
  18. HTML中alt标签的用法
  19. javascript 比较两个json数据是否相等
  20. 再保险系统涉及的概念

热门文章

  1. 感悟笔记(一)多思无益
  2. Rootkit 真刀真枪的权限保卫战
  3. win7系统的两种硬盘格式mbr和gpt怎么选择?
  4. 爬虫:python爬取简历模板
  5. 正弦函数的傅里叶级数展开计算
  6. 题目描述请参照本章例题,编写一个程序,输出以下信息:************************** Very Good**********************
  7. 路由器linux版本升级,华为路由器升级全攻略
  8. JavaScript的DOM知识点总结
  9. 双粗虚线中间一条实线_中间实线两边虚线是变道吗
  10. 下面哪段程序能够正确的实现了GBK编码字节流到UTF-8编码字节流的转换