大浪 淘沙 ini文件的读写

25 篇文章 0 订阅

原文地址:https://www.cnblogs.com/fuxianfeng1988/p/3292282.html

题目: INI文件操作库

INI文件就是扩展名为“ini”的文件。在Windows系统中,INI文件很多,最重要的就是“System.ini”、 “System32.ini”和“Win.ini”。该文件主要存放用户所做的选择以及系统的各种参数。用户可以通过修改INI文件,来改变应用程序和系统的很多配置。


    首先,我们先来了解下INI文件的结构。INI文件是一种按照特定方式排列的文本文件。每一个INI文件构成都非常类似,由若干段落(section)组成。在每个段落下面,是若干个以单个单词开头的关键词(key)和一个等号,等号右边的就是关键字对应的值(value)。即一般形式如下:

[Section1] 
KeyWord1 = Valuel 
KeyWord2 = Value2

[gmy_p]

exist_p=0

linux_p=123

其中[gmy_p]为section;exist_p为key;0为key的值value。

 

在本题中我们假设INI文件的结构中没有section部分,即我们所定义的inifile文件结构如下: 

Key1 = Valuel                

Key2 = Value2

我们需要实现一个能对inifile文件进行读写操作的库。该库通过包含inifile.h来调用。读操作中需要将文件中每行的key值和其对应的value值读出;写操作中需要将给定的key和value值按照inifile文件的结构写入文件中。

下面给出inifile.h中函数原型

int load(char * filename); #装载正常返回0

int read(char * section, char * key, char * stored_value);

int write(char * section, char * key, char * value_write);

 

需要写的程序:

(1)    在inifile.c中实现三个函数

(2)    写一个示例程序,看看infile这个库能不能正常工作。

 

提示:

由于不知道inifile中有多少个section和多少个value,所以需要用到链表来存储。

#####main.c#########


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "inifile.h"

int main(void)
{   
    int result;
    inifile_dest_t ifd;
    char *section, *key, *wvalue;
    char value[MAX_VALUE_LEN];

    memset(&ifd, 0, sizeof(inifile_dest_t));//将ifd中前sizeof(inifile_dest_t)个字节用 0 替换并返回ifd 。

    /* 加载ini文件 */
    result = load_ini(&ifd, "system.ini");
    if (result != 0) {
        
    }

    /* 显示ini文件内容 */
    //show_inifile_info(&ifd);

    /* 读取ini文件key的值 */
    memset(value, 0, MAX_VALUE_LEN);
    section = "drivers";
    key = "timer";
    result = read_ini(&ifd, section, key, value, MAX_VALUE_LEN);
    if (result != 0) {
        close_ini(&ifd);
        return -1;
    }
    printf("read inifile info:\r\n");
    printf("section: %s\r\n", section);
    printf("key    : %s\r\n", key);
    printf("value  : %s\r\n",value);

    /* 设置ini文件key的值 */
    section = "drivers";
    key = "timer";
    wvalue = "qingtian";
    result = write_ini(&ifd, section, key, wvalue);
    if (result != 0) {
        close_ini(&ifd);
        return -1;
    }
    printf("write inifile info:\r\n");
    printf("section: %s\r\n", section);
    printf("key    : %s\r\n", key);
    printf("value  : %s\r\n", wvalue);

    /* 关闭已经打开的ini文件,释放资源 */
    close_ini(&ifd);

    return 0;
}
################inifile.h#############


#ifndef _INIFILE_H_
#define _INIFILE_H_

#define MAX_SECTION_LEN  128        /* 最大section长度 */
#define MAX_KEY_LEN      128        /* 最大kye长度 */
#define MAX_VALUE_LEN    128        /* 最大value长度 */
#define MAX_BUFFER_LEN   128        /* 最大缓冲区长度 */

#define TRUE             1
#define FALSE            0


typedef struct section_enty_s {
    char *section;                   /* section name */
    char *key;                       /* key */
    char *value;                     /* key value */
    struct section_enty_s *next;
} section_enty_t;

typedef struct inifile_dest_s {
    char *filename;                  /* open ini file name */
    struct section_enty_s *enty;
} inifile_dest_t;

/* 读取ini文件,把文件信息保存到文件描述符句柄中 */
extern int load_ini(inifile_dest_t *ifd, char *filename);

/* 根据描述符句柄,读取key对应的值 */
extern int read_ini(inifile_dest_t *ifd, const char *section, const char *key, char *stored_value, int vlen);

/* 设置对应key的value值 */
extern int write_ini(inifile_dest_t *ifd, const char *section, const char *key, char *value_write);

/* 显示ini文件信息 */
extern void show_inifile_info(inifile_dest_t *ifd);

/* 关闭ini文件, 如果句柄有执行过write操作,将对应的key的值写回到文件中 */
extern int close_ini(inifile_dest_t *ifd);

#endif    /* _INIFILE_H_ */
#################inifile.c###################




#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "inifile.h"

/* 释放section节点 */
static void free_sect_enty(section_enty_t *enty)
{
    if (enty->section != NULL) {
        free(enty->section);
    }
    if (enty->key != NULL) {
        free(enty->key);
    }
    if (enty->value!= NULL) {
        free(enty->value);
    }
    free(enty);
}

/* 释放已经加载的ini文件 */
static void free_inifile_dest_enty(inifile_dest_t *ifd)
{
    section_enty_t *tmp, *p;

    tmp = ifd->enty;
    while (tmp != NULL) 
     {  
        p = tmp->next;
        free_sect_enty(tmp);
        tmp = p;
    }
}

/* 显示ini文件内容信息 */
void show_inifile_info(inifile_dest_t *ifd) 
{   
    section_enty_t *enty;

    if (ifd == NULL) {
        return;
    }
    
    printf("inifile name:%s\r\n", ifd->filename);
    enty = ifd->enty;
    while (enty != NULL) {  
        printf("section:%s\r\n", enty->section);
        printf("key    :%s\r\n", enty->key);
        printf("value  :%s\r\n", enty->value);
        enty = enty->next;
    }
}

/* 往inifile句柄中添加一section节点 */
static void add_section_to_ifd(inifile_dest_t *ifd, section_enty_t *enty) 
{    
    enty->next = ifd->enty;
    ifd->enty = enty;    
}

/* 更新值到ini文件中 */
static int write_info_back_inifile(inifile_dest_t *ifd, section_enty_t *enty)
{
    FILE *input, *output;
    char buf[MAX_BUFFER_LEN];
    char *ch, *tmp, *tmp_file;
    int  filename_len, wflags;

    /* 为临时文件添加"_tmp"文件名 */
    filename_len = strlen(ifd->filename);
    tmp_file = (char *)malloc(filename_len + 5);                //新建文件名为"system.ini_tmp",所以加4+1(结束符'\0')
    if (tmp_file == NULL) {
        printf("no enough memory!\r\n");
    }
    sprintf(tmp_file, "%s%s", ifd->filename, "_tmp");           //第一个参数是字符缓冲区,保存格式转换后的字符串;第二个是格式字符串

    input = fopen(ifd->filename, "r");                          //"r"模式下该文件必须存在
    if (input == NULL) {
        return -1;
    }
    output = fopen(tmp_file, "w");                              //"w"模式下若文件不存在则建立文件
    if (output == NULL) {
        return -1;
    }

    while ((ch = fgets(buf, MAX_BUFFER_LEN, input)) != NULL)    //失败或读到文件结尾时返回NULL
    {  
       if (strstr(buf, enty->section) != NULL) //从字符串buf中查找是否有字符串enty->section,若有则返回enty->section在buf中的起始位置的指针,否则,返回NULL
       {               
            wflags = 1;                                          
            fprintf(output, "%s", buf);                         //int fprintf(FILE *stream,char *format,[argument]),其作用是格式化输出到一个流/文件中
            continue;                                           //fprintf()函数根据指定的format(格式)发送信息(参数)到由stream(流)指定的文件. f
        }

        if ( strstr(buf, enty->key) != NULL) 
        {
            tmp = strchr(buf, '=');                             //对比函数strstr
            if (tmp != NULL) 
            {
                tmp++;
                strcpy(tmp, enty->value);
                wflags = 0;
                fprintf(output, "%s\n", buf);
                continue;
            }
        }
        
        fprintf(output, "%s", buf); 
    }

    fclose(input);
    fclose(output);

    /* 修改临时文件名 */
    (void)remove(ifd->filename);                   //int remove(const char *filename),删除一个文件
    (void)rename(tmp_file, ifd->filename);         //int rename(char *oldname, char *newname);给一个文件重命名
    free(tmp_file);
    
    return 0;
}


/**
 * load_ini - 读取ini文件,把文件信息保存到文件描述符句柄中 
 * @ifd     : ini文件句柄描述符指针
 * @filename: 文件名
 */
int load_ini(inifile_dest_t *ifd, char *filename)
{
    FILE *input;
    int  buflen, sect_len; //sect_flag;
    char buf[MAX_BUFFER_LEN];
    char sect[MAX_SECTION_LEN];
    char *ch, *tmp;
    char *begin, *end;
    section_enty_t *enty;

    if (ifd == NULL || filename == NULL) 
    {  
        return -1;
    }
    /* 将文件名称保存到句柄中 */
    ifd->filename = (char *)malloc(strlen(filename));
    if (ifd->filename == NULL) 
    {   
        return -1;
    }
    strcpy(ifd->filename, filename); //extern char *strcpy(char* dest, const char *src)

    input = fopen(filename, "r");
    if (input == NULL) 
    {  
        printf("open ini file error!\r\n");
        return -1;
    }
    /* read a line from file buffer */
    memset(buf, 0, MAX_BUFFER_LEN);
    memset(sect, 0, MAX_SECTION_LEN);
    //sect_len = sect_flag = 0;
    while ((ch = fgets(buf, MAX_BUFFER_LEN, input)) != NULL) //char *fgets(char *buf, int bufsize, FILE *stream);
    {    begin = buf;
        /* 删除头部的空格 */
        while(*begin == ' ') 
        {    
            begin++;
        }
        if (*begin == '\n' || *begin == ';') 
        {   
            continue;
        }
        tmp = strchr(buf, '[');  //找字符串buf中首次出现字符'['的位置
        if (tmp != NULL) 
        {    
            begin = tmp + 1;
            end = strchr(begin, ']');
            if (end == NULL)
            {   printf("the inifile is damaged!\r\n");
                continue;
            }
            /* 拷贝字符串内容到sect数组 */
            sect_len = end - begin;
            strncpy(sect, begin, sect_len);//复制begin中的前sect_len字节的内容到sect
            continue;
        }
        /* 处理key与对应的value字段 */
        if ((tmp = strchr(buf, '=')) != NULL) 
        {    
            enty = (section_enty_t *)malloc(sizeof(section_enty_t));
            if (enty == NULL) 
            {   printf("malloc section enty error!\r\n");
                fclose(input);
                free_inifile_dest_enty(ifd);
                return -1;
            }
            
            enty->section = (char *)malloc(sect_len+1*sizeof(char));//section长度再加上结束符'\0'
            if (enty->section == NULL) 
            {    
                printf("malloc section buffer error!\r\n");
                free(enty);
                fclose(input);
                free_inifile_dest_enty(ifd);
                return -1;
            }  
            strncpy(enty->section, sect, sect_len);
            *(enty->section+sect_len)='\0';

            
            /* 处理key内容 */
            buflen = tmp - begin;
            enty->key = (char *)malloc(buflen+1*sizeof(char));
            if (enty->key == NULL) 
            {   
                printf("malloc key buffer error!\r\n");
                free(enty->section);
                free(enty);
                fclose(input);
                free_inifile_dest_enty(ifd);
                return -1;
            }
            strncpy(enty->key, begin, buflen);
            *(enty->key+buflen)='\0';
            /* 处理value内容 */
            end = tmp++;
            while (*end != '\0' && *end != '\n') 
            {
                end++;
            }
            buflen = end - tmp;
            enty->value = (char *)malloc(buflen+1*sizeof(char));
            if (enty->value == NULL) 
            {   
                printf("malloc value buffer error!\r\n");
                free(enty->section);
                free(enty->key);
                free(enty);
                fclose(input);
                free_inifile_dest_enty(ifd);
                return -1;
            }
            strncpy(enty->value, tmp, buflen);
            *(enty->value+buflen)='\0';

            /* 配置信息挂到inifile句柄中 */
            add_section_to_ifd(ifd, enty);
        }
    }

    fclose(input);

    return 0;
}

/**
 * read_ini - 根据描述符句柄,读取key对应的值
 * @ifd    : inifile句柄描述符
 * @section: 段值
 * @key    : key值
 * @stored_value: 存储ini文件中的key对应的值
 * @vlen   : 保存value值空间的长度
 */
int read_ini(inifile_dest_t *ifd, const char *section, const char *key, char *stored_value, int vlen)
{
    section_enty_t *enty, *tmp;

    if (ifd == NULL || section == NULL || key == NULL || stored_value == NULL) {
        return -1;
    }

    tmp = ifd->enty;
    while (tmp != NULL) {
        enty = tmp;
        if ((strcmp(enty->section, section) == 0) && (strcmp(enty->key, key) == 0)) 
         {   
            strncpy(stored_value, enty->value, vlen);
            break;
        }   
        tmp = tmp->next;
    }
    
    return 0;
}

/**
 * write_ini - 设置对应key的value值
 * @ifd    : inifile句柄描述符
 * @section: 段值
 * @key    : key值
 * @value_write: 设置key对应的值
 */
int write_ini(inifile_dest_t *ifd, const char *section, const char *key, char *value_write)
{
    section_enty_t *enty, *tmp;
    char *ch;
    int  vlen;

    if (ifd == NULL || section == NULL || key == NULL || value_write == NULL) {
        return -1;
    }

    tmp = ifd->enty;
    while (tmp != NULL) {
        enty = tmp;
        if ((strcmp(enty->section, section) == 0) && (strcmp(enty->key, key) == 0)) {
            vlen = strlen(value_write);
            ch = (char *)malloc(vlen+1*sizeof(char));
            if (ch == NULL) {
                printf("malloc value error!\r\n");
                return -1;
            }
            free(enty->value);
            enty->value = ch;
            strncpy(enty->value, value_write, vlen);
            *(enty->value+vlen)='\0';
            write_info_back_inifile(ifd, enty);
            break;
        }   
        tmp = tmp->next;
    }
    
    return 0;
}

/* 关闭ini文件, 如果句柄有执行过write操作,将对应的key的值写回到文件中 */
int close_ini(inifile_dest_t *ifd)
{
    if (ifd == NULL) {
        return -1;
    }
    
    free_inifile_dest_enty(ifd);

    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值