`
king_tt
  • 浏览: 2107551 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

纯C语言INI文件解析

 
阅读更多

在一个跨平台( 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文件

    C语言 ini文件解析 linux 下测试程序,使用方法直接make即可

    c语言实现ini文件读写操作

    该INI文件读写操作的实现主要包括解析INI文件的结构,提取和设置配置项的值,以及将修改后的配置信息写回文件。C语言提供了丰富的标准库函数,使得处理文本文件和字符串操作变得简单高效。通过编写相应的读取和写入...

    一个简单的用C语言编写的INI文件解析器

    它只有几页代码,而且设计得小而简单,因此非常适合嵌入式系统。

    配置文件(ini)解析器C语言版

    原创的INI配置文件解析器,提供了完善而简洁的一组INI文件操作接口,能以非常灵活地方式来返回键值、设置键值、删除键、添加新键、创建新的INI文件等。同时支持(但不仅限于)Linux GCC/Windows VC平台。在这里共享出...

    一个INI文件解析程序

    LINUX下面运行的INI解析程序,c语言版本

    ini格式配置文件解析和写入库

    使用C语言编写的使用于ini配置文件的读写,能方便的解析,组织,写入ini文件

    XXX.ini 配置文件解析工具库 - C语言版本

    XXX.ini 配置文件解析工具库,C语言版本。

    配置文件解析器

    使用c语言实现的轻量级ini配置文件解析器,不依赖其他动态库

    iniparser-master-v4.1-2018-08-02

    C语言配置文件解析库 — Iniparser库可以方便的对ini文件(配置文件)进行解析、设置、删除等操作。

    学生管理系统V1.0,主要使用C语言实现

    文件主要包括:main.c、JSYStudentMsg.txt、UserIni.ini、学生管理系统数据结构解析图.png、学生管理系统思维导图.png。该项目内置典型C语言继承逻辑以及动态数组和链表数据结构。主要实现功能为:登录用户名和密码...

    WinCE脚本解析程序(写写文本就能做很多意想不到的事情)

    使用C语言和Windows API编写,作了一些特殊处理以同时支持WinCE5和WinCE6,主要实现shell中的功能,提供的各种操作涉及到文件系统、窗口管理、进程管理和流程控制几个方面,通过解析配置文件内容来执行相应的操作,...

    文本配置文件读写

    这个代码用于读写配置文件,分为Section、Key、Value三部分,用C语言编写,适合各种应用场合,非常实用,代码精简高效,单片机也能使用,linux、windos就更不在话下了。

    CETool(最新2013.8)

    使用C语言和Windows API编写,作了一些特殊处理以同时支持WinCE5和WinCE6,主要实现shell中的功能,提供的各种操作涉及到文件系统、窗口管理、进程管理和流程控制几个方面,通过解析配置文件内容来执行相应的操作,...

    vc源代码合集0951.rar

    2012-06-12 12:12 45,056 VC++操作INI配置文件的实现.doc 2012-06-12 11:48 11,728,284 VC++数字图像模式识别技术及工程实践.pdf 2012-06-12 12:58 1,863,715 VC++设置和获得一组单选按钮的选中状态.rar 2012-06-12 ...

    winxp系统结构5课(注册表)->1认识注册表

    三,读取boot.ini文件,c:\下的boot.ini和bootsect.dos配合来完成多操作系统的管理。 四,加载NtDetect.com文件:此文件的作用是检测计算机硬件,如并口,显示适配器等设备, 并将收集到的信息的硬件列表...

Global site tag (gtag.js) - Google Analytics