ini文件的读写

题目: 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; }

 

 

posted on 2013-08-30 19:15  大浪 淘沙  阅读(1406)  评论(0编辑  收藏  举报

导航