linux c 自己实现ini格式的reader

ini_reader.c


/*
* brief: ini文件读取方法
* author: chengs
* date: 2024.05.13
*/
#include <glib.h>

#include "ini_reader.h"
#include "log.h"
#include "zstring.h"

/**
 * 
 * 作用: 将psect 当section加入ini
 * 参数: psect 为section的名字,pini_file为ini文件
 *  
 * */
void AddSection(const pchar psect, GPtrArray_autoptr pini_file)
{
    PINI_SECTION pini_section = malloc(sizeof(INI_SECTION));
    
    memset(pini_section, 0, sizeof(INI_SECTION));

    SetZString(psect, &pini_section->str_section);

    g_ptr_array_add(pini_file, (gpointer) pini_section);
}

/**
 * 
 * 作用: 将ini读入数组
 * 参数: 需要读入的ini
 *  
 * */
GPtrArray_autoptr read_ini_to_array(pchar file_name)
{
	if (!file_name)
	{
		log_error(__FILE__, __LINE__, "file_name is null");

		return NULL;
	}

    FILE *fp = NULL;

    fp = fopen(file_name, "r");

    if (fp == NULL)
    {
        log_error(__FILE__, __LINE__, "fp is null file_name: %s", file_name);

        return NULL;
    }

    char sLine[INI_LINE_NUM]={0};
    char sSect[INI_SECTION_LEN]={0};
    char sKey[INI_KEY_LEN]={0};
    char sValue[INI_VALUE_LEN]={0};

    GPtrArray_autoptr pini_file = g_ptr_array_new(); 

    while (fgets(sLine, INI_LINE_NUM, fp) != NULL)
    {
        memset(sValue, 0, INI_VALUE_LEN);

        memset(sSect, 0, INI_SECTION_LEN);

        // 去除末尾换行符
        sLine[strcspn(sLine, "\n")] = '\0';

        if (sLine[0]==';' || sLine[0]=='#' || sLine[0]=='\0' || sLine[0]==' ' || sLine[0]=='\r\n')
            continue;

        if (sLine[0]=='[')
        {
            sscanf(sLine, "[%[^]]", sSect);

            AddSection(sSect, pini_file);
        }
        else
        {
            sscanf(sLine, "%[^=]=%[^\r\n]", sKey, sValue);
            
            if (pini_file->len == 0)
               AddSection(DFT_INI_SECTION, pini_file); 

            PINI_SECTION pini_section = (PINI_SECTION)g_ptr_array_index(pini_file, pini_file->len - 1);

            if (pini_section->pchild_kv == NULL)
                pini_section->pchild_kv = g_ptr_array_new();
            
            PINI_CHILD pini_child = malloc(sizeof(INI_CHILD));

            g_ptr_array_add(pini_section->pchild_kv, (gpointer) pini_child);

            SetZString(sKey, &pini_child->str_key);

            SetZString(sValue, &pini_child->str_value);

            // TODO: 保存参数
        }
    }
    
    fclose(fp);

    return pini_file;
}

/**
 * 
 * 作用: 从ini文件中查找某个section下,是否存在某个key
 * 参数: str_key ,key值
 *  
 * */

bool find_ini_key(GPtrArray_autoptr pini_file, const char* str_section, const char* str_key)
{
    if (NULL == pini_file || NULL == str_section || NULL ==  str_key)
    {
        log_error(__FILE__, __LINE__, "NULL == pini_file || NULL == str_section || NULL ==  str_key ;\
            pini_file = %p, str_section = %p, str_key = %p", pini_file, str_section, str_key);

        return false;
    }

    bool bfind = false;

    for (int i = 0; i < pini_file->len; i++)
    {
        if (bfind)
        {
            log_info(__FILE__, __LINE__, " bfind is true");

            break;
        }
        
        PINI_SECTION pini_section = (PINI_SECTION)g_ptr_array_index(pini_file, i);

        log_info(__FILE__, __LINE__, "section: %s", pini_section->str_section.value);

        if (strcmp(pini_section->str_section.value , str_section) != 0)
            continue;

        for (size_t i = 0; i < pini_section->pchild_kv->len; i++)
        {
            PINI_CHILD pini_child = (PINI_CHILD)g_ptr_array_index(pini_section->pchild_kv, i);

            log_info(__FILE__, __LINE__, "key: %s", pini_child->str_key.value);
            
            log_info(__FILE__, __LINE__, "value: %s",  pini_child->str_value.value);
            
            if(strcmp(pini_child->str_key.value, str_key) == 0)
            {
                bfind = true;

                break;
            }
        }
    }  
    return bfind;
}

/**
 * 
 * 作用: pini_file的内存释放
 * 参数: 需要释放的ini
 *  
 * */
void release_ini(const GPtrArray_autoptr pini_file)
{
    for (int i = 0; i < pini_file->len; i++)
	{
        PINI_SECTION pini_section = (PINI_SECTION)g_ptr_array_index(pini_file, i);

		log_info(__FILE__, __LINE__, "section: %s", pini_section->str_section);

		for (size_t i = 0; i < pini_section->pchild_kv->len; i++)
		{
			PINI_CHILD pini_child = (PINI_CHILD)g_ptr_array_index(pini_section->pchild_kv, i);

			log_info(__FILE__, __LINE__, "release key: %s", pini_child->str_key.value);

			log_info(__FILE__, __LINE__, "release value: %s",  pini_child->str_value.value);

            free(pini_child->str_key.value);

            free(pini_child->str_value.value);
		}

        free(pini_section->str_section.value);
	}

    g_ptr_array_free(pini_file, true);
}

/**
 * 
 * 作用: 将文件按行读入数组
 * 参数: 需要读的文件名
 *  
 * */
GPtrArray_autoptr read_line_to_array(pchar file_name)
{
	if (!file_name)
	{
		log_error(__FILE__, __LINE__, "file_name is null");

		return NULL;
	}

    FILE *fp = NULL;

    fp = fopen(file_name, "r");

    if (fp == NULL)
    {
        log_error(__FILE__, __LINE__, "fp is null file_name: %s", file_name);

        return NULL;
    }

    char sLine[INI_LINE_NUM]={0};
     
    GPtrArray_autoptr pfile = g_ptr_array_new(); 

    while (fgets(sLine, INI_LINE_NUM, fp) != NULL)
    {
        // 去除末尾换行符
        size_t pos = strcspn(sLine, "\n");
        if(pos >= 0 && pos < strlen(sLine))
            sLine[pos] = '\0';
        // 去除末尾/r
        pos = strcspn(sLine, "\r");
        if(pos >= 0 && pos < strlen(sLine))
            sLine[pos] = '\0';

        if (strcmp("",sLine) == 0)
            continue; //排除空行

        PZSTRING pzstring = malloc(sizeof(ZSTRING));

        SetZString(sLine, pzstring);

        g_ptr_array_add(pfile, (gpointer) pzstring);
    }
    
    fclose(fp);

    return pfile;
}

void release_line_array(GPtrArray_autoptr line_array)
{
    if (!line_array)
        return;
    
    for (size_t i = 0; i < line_array->len; i++)
    {   
        char temp[MAX_PATH] = {0};
        PZSTRING pfile = (PZSTRING)g_ptr_array_index(line_array, i);
        free(pfile->value);
    }

    g_ptr_array_free(line_array, true);
}

ini_reader.h

#ifndef _INI_READER_H_
#define _INI_READER_H_

#include "ztype.h"

#define DFT_INI_SECTION "default_0"

#define INI_LINE_NUM 512
#define INI_SECTION_LEN 64
#define INI_KEY_LEN 128
#define INI_VALUE_LEN 128

typedef struct INI_CHILD_STRU
{
    ZSTRING str_key;
    ZSTRING str_value;
}INI_CHILD,*PINI_CHILD;

typedef struct INI_SECTION_STRU
{
    ZSTRING str_section;
    GPtrArray_autoptr pchild_kv;
}INI_SECTION,*PINI_SECTION;

/**
 * 
 * 作用: 将psect 当section加入ini
 * 参数: psect 为section的名字,pini_file为ini文件
 *  
 * */
void AddSection(const pchar psect, GPtrArray_autoptr pini_file);

/**
 * 
 * 作用: 将ini读入数组
 * 参数: 需要读入的ini
 *  
 * */
GPtrArray_autoptr read_ini_to_array(pchar file_name);

/**
 * 
 * 作用: 从ini文件中查找某个section下,是否存在某个key
 * 参数: str_key ,key值
 *  
 * */

bool find_ini_key(GPtrArray_autoptr pini_file, const char* str_section, const char* str_key);

/**
 * 
 * 作用: pini_file的内存释放
 * 参数: 需要释放的ini
 *  
 * */
void release_ini(const GPtrArray_autoptr pini_file);

/**
 * 
 * 作用: 将文件按行读入数组
 * 参数: 需要读的文件名
 *  
 * */
GPtrArray_autoptr read_line_to_array(pchar file_name);
#endif

代码中使用了glib库作为数据结构,如果使用其他的,请自行替换。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 读写ini文件在Linux环境下可以使用多种方式实现。其中比较常用的有通过bash脚本和使用编程语言如C语言实现。 在bash脚本中,我们可以使用命令行工具如sed、awk、grep等来读写ini文件。比如,我们可以通过grep命令来查找ini文件中的特定配置项,然后使用sed命令来修改或添加配置项的值。同时,可以使用echo命令将配置项写入ini文件中。 另外,我们还可以使用C语言来读写ini文件。对于读取ini文件,可以使用标准C库中的文件操作函数,如fopen、fread等来实现。在写入ini文件时,可以使用fprintf函数将配置项写入文件中。 总之,就读写ini文件而言,可以根据具体的需求和环境选择合适的方式实现。无论是使用bash脚本还是编程语言,都可以灵活地读取和修改ini文件中的配置项。 ### 回答2: 在Linux环境中读写INI文件,可以使用C语言编写程序来实现。 首先,需要使用标准C库中的文件操作函数来打开和读取INI文件。可以使用fopen()函数打开INI文件,并使用fgets()函数逐行读取文件内容。对于每一行内容,使用字符串处理函数来解析出键值对。 同时,可以定义结构体来存储键值对的信息。结构体可以包含两个成员,一个成员用于存储键的名称,另一个成员用于存储键对应的值。 读取INI文件的过程中,可以使用字符串处理函数来解析每一行的内容。可以使用strtok()函数将每一行内容按照等号 "=" 分割成键和值。然后可以使用strcpy()函数将键和值的内容分别复制给对应的结构体成员。 读取完INI文件内容后,可以关闭文件,释放资源。 对于写INI文件,可以使用标准C库中的文件操作函数打开文件,并使用fprintf()函数向文件中写入键值对信息。可以按照INI文件的格式,将键和值以等号 "="分割,并在写入时添加对应的注释信息。 写入INI文件完成后,可以关闭文件,释放资源。 需要注意的是,读写INI文件需确保文件的编码格式为ASCII或UTF-8,以免出现乱码问题。同时,还应注意处理异常情况,如文件不存在或读写失败等,以保证程序的健壮性。 以上是使用C语言Linux环境中读写INI文件的基本过程。具体的实现方式可根据实际需求和个人编程经验进行调整和优化。 ### 回答3: 在Linux环境下,可以使用C语言读写ini配置文件。首先需要创建一个ini配置文件,它是一种文本文件,通常以.ini为扩展名。ini配置文件的格式是键值对的形式,由多个节(section)组成,每个节中可以包含多个键(key)和对应的值(value)。 读取ini配置文件可以通过使用C语言中的标准库函数来实现。首先使用fopen函数打开ini配置文件,并以只读模式("r")打开。然后通过fgets函数逐行读取文件内容,判断每一行是否为节或键值对。如果是节,则可以将节名存储起来,如果是键值对,则可以将键和值分别存储起来。 写入ini配置文件可以通过使用C语言中的标准库函数来实现。首先使用fopen函数打开ini配置文件,并以写入模式("w")打开。然后将要写入的节、键和值格式化成字符串,并通过fprintf函数将其写入文件中。需要注意的是,在写入之前可能需要先将原有的ini配置文件内容备份,以免丢失。 除了使用标准库函数之外,也可以使用开源的第三方库,如libini等,来更方便地读写ini配置文件。这些库提供了更简单的接口和函数,能够更便捷地读取和修改ini文件。在使用这些库时,需要先安装相应的库文件,并在编译时链接库文件。 总之,通过C语言可以在Linux环境下读写ini配置文件。读取可以使用标准库函数或第三方库函数,写入则可以使用标准库函数或第三方库函数。具体的实现方式可以根据实际需求和情况选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值