在项目里面经常会用到读取一些配置信息,而C语言有没有直接的读取配置文件的函数,这里贴出我写的代码,有兴趣的看一下,也希望能有好的建议。
考虑到代码需要在多个项目里面运行,会对配置文件有不同的需求,这里把文件路径封装在一个struct里面,方便在里面添加一些其他的变量,头文件声明如下:
hcof.c
/****************************************************************** * 用途: 配置文件读写 * * 作者: uehang * * 日期: 2013-3-28 * *****************************************************************/ #ifndef HCONF_H #define HCONF_H #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> typedef struct h_conf{ char file_path[200]; }HConf; void init_conf(HConf *hconf, char *file_path); /* * return: -1:fail to open file; 0: can not find the key; 1: success */ int get_conf_value(HConf *hconf, char *key_name, char *value); /* * return: -1:fail to open file; 0: can not find the key; 1: success */ int set_conf_value(HConf *hconf, char *key_name, char *value); #endif
首先,初始化函数,对当前的情况来说,只负责把参数file_path的值传递到参数hcnf的file_path变量,这里单独写成一个函数,不仅是让get_conf_value()和set_conf_value()在调用时避免写一长串的file_path,也是方便在有特殊需求的情况下,对文件名进行检验或对文件进行预处理。
get_conf_value()与set_conf_value()负责读写文件,由于配置文件多是在程序启动或者特殊时刻才会读取,所以没有必要一直打开文件。
hconf.c
#include "hconf.h" void init_conf(HConf *hconf, char *file_path) { int fd=open(file_path,O_RDONLY); if(fd>2){ //确保文件存在 close(fd); strcpy(hconf->file_path,file_path); }else{ perror("can not open config file:"); } } int get_conf_value(HConf *hconf, char *key_name, char *value) { int res; int fd = open(hconf->file_path,O_RDONLY); if(fd > 2){ res = 0; char c; char *ptrk=key_name; char *ptrv=value; while((read(fd,&c,1))==1){ if(c == (*ptrk)){ do{ ptrk ++; read(fd,&c,1); }while(c == (*ptrk)); if(c=='='&&(*ptrk)=='\0'){ while(1) { read(fd,&c,1); if(c != '\n') { (*ptrv) = c; ptrv ++; }else{ (*ptrv) = '\0'; break; } } res = 1; break; }else{ do{ read(fd,&c,1); }while(c != '\n'); } }else{ do{ read(fd,&c,1); }while(c != '\n'); } } close(fd); }else{ res = -1; } return res; } int set_conf_value(HConf *hconf, char* key_name, char *value) { int res; int fd = open(hconf->file_path,O_RDONLY); if(fd > 2){ char buf[800]; //存储文件内容 res = 0; char c; char *ptrk=key_name; char *ptrv=value; char *ptrb=buf; while((read(fd,&c,1))==1){ *ptrb = c; if(c == *ptrk){ do{ ptrb ++; ptrk ++; read(fd,&c,1); *ptrb = c; }while(c == *ptrk); if(c == '=' && *ptrk == '\0'){//找到目标行 do{ ptrb ++; *ptrb = *ptrv; ptrv ++; }while(*ptrv != '\0'); //将value赋值给buf while((read(fd,&c,1)) == 1 && c != '\n');//等号右边原来的内容舍弃 ptrb ++; *ptrb = '\n'; }else { //非目标行全部读取 while((read(fd,&c,1)) == 1){ ptrb ++; *ptrb = c; if(c == '\n'){ break; } } } }else{ //非目标行全部读取 while((read(fd,&c,1)) == 1){ ptrb ++; *ptrb = c; if(c == '\n'){ break; } } } ptrb ++; } *ptrb = '\0'; //循环结束,buf末尾置'\0' close(fd); fd=open(hconf->file_path,O_WRONLY|O_TRUNC);//截短打开文件,写入buf if(fd > 2){ write(fd,buf,strlen(buf)); close(fd); res = 1; } }else{ res = -1; } return res; }
所有打开的文件都有一个当前文件偏移量(current file offset),可以简称为 cfo。cfo 通常是一个非负整数,用于表明文件开始处到文件当前位置的字节数。读写操作通常开始于 cfo,并且使 cfo 增大,增量为读写的字节数。文件被打开时,cfo 会被初始化为 0,除非使用了 O_APPEND 。这里通过每次的read()和write()函数来改变偏移量,使定位准确。
由于c语言中的文件是以数据流的形式来进行读写的,无法直接进行插入、删除的操作,这里把文件内容经处理后全部读取到内存里面,然后从内存写入到原文件里面,实现对文件的修改。
测试
这里用一个简单的文件测试一下
main.c
#include <stdio.h> #include <stdlib.h> #include "hconf.h" int main() { HConf *info = (HConf *) malloc(sizeof(HConf)); init_conf(info,"./info.conf"); char buf[20]; get_conf_value(info,"email",buf); printf("email = %s --get from info\n",buf); set_conf_value(info,"age","115 years old"); printf("set info:age = 115 years old\n"); return 0; }
结果:
原info.conf 运行后info.conf
总结
总的来说,是实现了基本读写功能,而且只用了文件操作的open()、read()、write()这三个函数,而在测试时也发现,对中文的比较和判断会出错,若有大侠路过,也恳求指点。