纯C语言INI文件解析
原地址:http://blog.csdn.net/foruok/article/details/17715969
在一个跨平台( 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文件解析的更多相关文章
- ini文件解析c库(iniparser)
一.交叉编译ini解析库 1.官方网站http://ndevilla.free.fr/iniparser 下载iniparser-3.1.tar.gz 2.解压 tar -zxvf iniparser ...
- ini文件解析c库(iniparser)【转】
转自:http://www.cnblogs.com/dyllove98/archive/2013/07/28/3221732.html 一.交叉编译ini解析库 .官方网站http://ndevill ...
- 超赞的 Go 语言 INI 文件操作
灵活的数据源 不光光可以从文件读取配置,还支持 []byte 类型的纯数据读取和基于 io.ReadCloser 的流式读取. 多种格式兼容 各种文件种类的广泛支持,包括但不限于 my.cnf..gi ...
- C++——INI文件详解
原创声明:本文系博主原创文章,转载及引用请注明出处. 1. INI文件介绍 INI是英文单词 INItialization 的缩写,常作为Windows系统下的配置文件.INI文件是文本文件,通常用于 ...
- boost::property_tree读取解析ini文件--推荐
boost::property_tree读取解析ini文件 #include "stdafx.h" #include <iostream> #include <b ...
- 实战parse_ini_file()及扩展函数解析ini文件完整版
文章来源:PHP开发学习门户 地址:http://www.phpthinking.com/archives/587 在PHP站点开发的过程中,往往会用到读取ini參数配置文件,比方须要訪问一些复杂的借 ...
- python解析ini文件
python解析ini文件 使用configparser - Configuration file parser sections() add_section(section) has_section ...
- 解决ini-parser解析ini文件中文乱码问题
rickyah/ini-parser 是一个.net 平台解析ini文件的库,当ini文件中含有中文字符时会乱码. 解决:将文件通过Editplus 等文本编辑工具保存为 utf-8 + bom 格式 ...
- 【WPS】表格使用VBA宏编程写入ini文件实现软件多语言
前言:公司软件最近在做多语言版本,而又来一个西班牙文版本的,之前已经做过中文版本,英文版本和法文版本,之前是同事做的,现在安排我做,之前的做法,使用wps表格,翻译好,然后一个一个复制粘贴到ini文件 ...
随机推荐
- 基于visual Studio2013解决C语言竞赛题之0612递归
题目
- Savitzky-Golay滤波器(2)
前几天写过一篇介绍 Savitzky-Golay滤波器的文章, 没想到最近做项目还真的用上了. 因此就顺便写了个 C 语言的自动计算生成 SG 滤波器系数的程序.利用这里的代码可以生成任意阶数的 SG ...
- 在vc中使用xtremetoolkit界面库-----安装及环境配置
近期想用一下xtremetoolkitPro界面库.网上的使用教程资源也不多,当中着实遇到了很多的困难,毕竟是首次使用. 首先当然是配置发开环境了: 我使用的是vc6.0+xtremetoolkitP ...
- CentOS: make menuconfig error: curses.h: No such file or directory
the problem when use centos5 to build kernel or busybox step 1. Centos中关于 ncurses.h:no such file or ...
- BZOJ 1179: [Apio2009]Atm( tarjan + 最短路 )
对于一个强连通分量, 一定是整个走或者不走, 所以tarjan缩点然后跑dijkstra. ------------------------------------------------------ ...
- ORACLE实例恢复过程详细分析--使用dump、BBED等多种工具结合分析
---友情提示,内容较多,可以从博文左上的+目录选择小节方便阅读. 实验思路: --实验相关TRACE文件:http://download.csdn.net/detail/q947817003/6 ...
- 基于visual Studio2013解决C语言竞赛题之1013字符串查找
题目 解决代码及点评 /* 功能:编写函数IND,让它判断一个字符串是否为另一个字符串的子串的功能,若是则返回第一次出现的起始位置,否则返回0 时间:13:55 2013 ...
- 基于visual Studio2013解决C语言竞赛题之1038数字验证
题目 解决代码及点评 /********************************************************************** ...
- Java面试题精选(三) JSP/Servlet Java面试逻辑题
-- JSP/Servlet Java面试逻辑题 -- 很显然,Servlet/JSP的WEB前端动态制作的重要性比HTML/CSS/JS的价值高很多,但我们都知道他们都是建立在HT ...
- axure制作项目符号列表样式
1. 拖动文本面板到页面编辑区域 2. 点击工具栏的[项目符合列表] 来自:非原型不设计