配置文件读写工具(c语言实现)

一,
实现了一个灵活的读取或设置配置文件中的键-值中的值的功能
使用规则如下
1,键-值之间的连接符可以自定义指定,不固定
2,对配置文件的大小没有限制,可随意大小
3,键,连接符,值依次出现一行,三者之间不能有重叠
4,对于设置函数,如果不存在对应的键,则会在配置文件最后一行自动添加
5 对于每行除空格字符外第一个字符为‘#’,则该行会被当成注释行
二,有五个文件分别为conf_file.c conf_file.c test.c Makfile test.ini,
可直接通过make命令进行编译
其中conf_file.c conf_file.h为接口工具文件
test.c为测试文件
Makefile为编译指令文件
test.in测试用配置文件名
三,优点;该工具经过测试,开发人员可直接使用,节约开发效率
四 ,源码展示如下
1, conf_file.c

#include
#include
#include


/*
实现了一个灵活的读取或设置配置文件中的键-值中的值的功能
1,键-值之间的连接符可以自定义指定,不固定
2,对配置文件的大小没有限制,可随意大小
3,键,连接符,值依次出现一行,三者之间不能有重叠 
4,对于设置函数,如果不存在对应的键,则会在配置文件最后一行自动添加
5 对于每行除空格字符外第一个字符为‘#’,则该行会被当成注释行
*/ 
#define CONF_FILE_MAX_LINE_SIZE 128   //配置文件中的每行的字符个数不能超过128个 否者该行的内容会被被删掉
struct conf_file_list_str;
typedef struct conf_file_list_str{
    char str[CONF_FILE_MAX_LINE_SIZE];
    struct conf_file_list_str *next;
}CONF_FILE_LIST;


/*
***********************************************************
 *函数名:Is_ALL_Special_Character
 *功   能:判断从p开始 len长度的地址空间所指向的字符是否都为symbol
 *输   入:
 *输   出:
 *返回 值:是返回0;否者返回-1
 *说  明:
 *************************************************************
 */
static int Is_ALL_Special_Character(char *p, int len, char symbol){
    int i;
    for(i = 0; i < len; i++){
        if(p[i] != symbol) return -1;
    }
    return 0;
}



/*
***********************************************************
 *函数名:conf_file_set_value_by_key
 *功   能:根据提供的键设置配置文件中的值,如果指定的键不存在,则在最后一行添加
 *输   入:file[in]:配置文件名;key[in]:键-值中的键;symbol[in]:处于键-值之间的的符号,
         该符号必须具备将键-值区别开的能力,即键,值中不能包含该字符;value[in]:键-值中的值
 *输   出:key
 *返回 值:成功返回0,如果返回-1
 *说  明:
 *************************************************************
 */
int conf_file_set_value_by_key(const char *file, const char *key,const char symbol, const char *value){
    int ret = -1;
    FILE *pfile = fopen(file, "r");//以写模式打开文件,如果该文件不存在,则创建该文件
    if(!pfile) {
        perror(fopen);
        return -1;
    }
        
    CONF_FILE_LIST *root_node = NULL, *temp_node, *pre_node = NULL, *tail_node;
    CONF_FILE_LIST *curr_node = (CONF_FILE_LIST*)malloc(sizeof(CONF_FILE_LIST));
    curr_node ->next = NULL;
    root_node = curr_node;
    pre_node = NULL;
    char *p, *p1;
    int p_len = CONF_FILE_MAX_LINE_SIZE;
    while(fgets(curr_node->str, CONF_FILE_MAX_LINE_SIZE, pfile)){
        if(!root_node) root_node = curr_node;
        temp_node = (CONF_FILE_LIST*)malloc(sizeof(CONF_FILE_LIST));
        memset(temp_node->str, 0, CONF_FILE_MAX_LINE_SIZE);
        temp_node->next = NULL;
        curr_node->next = temp_node;
        pre_node = curr_node;
        curr_node = temp_node;
    }
    tail_node = curr_node;
    curr_node = root_node;
    //首先查收是否有换行符
    while(curr_node){
        //判断是否有换行符
        p = curr_node->str;
        p_len = CONF_FILE_MAX_LINE_SIZE;
        if(NULL == (p1 = strchr(p, '#')) || 0 != Is_ALL_Special_Character(p, p1 - p, ' ')){
            if(NULL != (p1 = strstr(p, key)) && 0 == Is_ALL_Special_Character(p, p1 - p, ' ')){
               p_len -= (p1 - p);
               p = p1;                                                                                                                                                                                             
               p += strlen(key);
               p_len -= strlen(key);
               if(NULL != (p1 = strchr(p, symbol)) && 0 == Is_ALL_Special_Character(p, p1 - p, ' ')){
                   p_len -= (p1 - p);
                   p = p1;
                   p_len --;
                   p++;
                   int temp_len = strlen(value);
                   if((p_len -2) < temp_len) 
                       goto err1;                
                   memset(p, 0, p_len);               
                   strcpy(p, value);
                   p[temp_len] = '\n';
                   p[temp_len + 1] = '\0';
                   break;
               }
            }
        }
        curr_node = curr_node->next;
    }   
    //一定是链表节点遍历到了最后一个节点
    if(curr_node == NULL){
        
        if(strlen(key) + 1 + strlen(value) > (CONF_FILE_MAX_LINE_SIZE - 3)) 
            goto err1;
        char *p = tail_node->str;
        *p = '\n';
        p++;
        strcpy(p, key);
        p += strlen(key);
        *p = symbol;
        p++;
        strcpy(p, value);
        p += strlen(value);
        *p = '\n';
        p++;
        *p = '\0';
    }else{ 
        pre_node->next = NULL;
        free(tail_node);
    }
    ret = 0;
err1:
    
    fclose(pfile);
    pfile = fopen(file, "w+");//以写模式打开文件,如果该文件不存在,则创建该文件
    curr_node = root_node;
    while(curr_node){
        fputs(curr_node->str, pfile);  
        pre_node = curr_node;
        curr_node = curr_node->next;
        free(pre_node);
    }
    fclose(pfile);
    return ret;
}

/*
***********************************************************
 *函数名:conf_file_set_value_by_key
 *功   能:根据提供的键设置配置文件中的值,如果指定的键不存在,则在最后一行添加
 *输   入:file[in]:配置文件名;key[in]:键-值中的键;symbol[in]:处于键-值之间的的符号,
         该符号必须具备将键-值区别开的能力,即键,值中不能包含该字符;value[in]:键-值中的值
 *输   出:key
 *返回 值:成功返回0,如果返回-1
 *说  明:
 *************************************************************
 */
int conf_file_get_value_by_key(const char *file,const  char *key,const char symbol, char *value){
    int ret = 0;
    FILE *pfile = fopen(file, "r");//以写模式打开文件,如果该文件不存在,则创建该文件
    if(!pfile) {
        perror(fopen);
        return -1;
    }
    CONF_FILE_LIST *root_node = NULL, *temp_node, *pre_node = NULL;
    CONF_FILE_LIST *curr_node = (CONF_FILE_LIST*)malloc(sizeof(CONF_FILE_LIST));
    curr_node ->next = NULL;
    root_node = curr_node;
    pre_node = NULL;
    char *p, *p1;
    int p_len = CONF_FILE_MAX_LINE_SIZE;
    while(fgets(curr_node->str, CONF_FILE_MAX_LINE_SIZE, pfile)){
        if(!root_node) root_node = curr_node;
        temp_node = (CONF_FILE_LIST*)malloc(sizeof(CONF_FILE_LIST));
        memset(temp_node->str, 0, CONF_FILE_MAX_LINE_SIZE);
        temp_node->next = NULL;
        curr_node->next = temp_node;
        pre_node = curr_node;
        curr_node = temp_node;
    }
    curr_node = root_node;
    //首先查收是否有换行符
    while(curr_node){
        //判断是否有换行符
        p = curr_node->str;
        p_len = CONF_FILE_MAX_LINE_SIZE;
        if(NULL == (p1 = strchr(p, '#')) || 0 != Is_ALL_Special_Character(p, p1 - p, ' ')){
            if(NULL != (p1 = strstr(p, key)) && 0 == Is_ALL_Special_Character(p, p1 - p, ' ')){
                p_len -= (p1 - p);
                p = p1;                                                                                                                                                                                        
                p += strlen(key);
                p_len -= strlen(key);
                if(NULL != (p1 = strchr(p, symbol)) && 0 == Is_ALL_Special_Character(p, p1 - p, ' ')){
                    p_len -= (p1 - p);
                    p = p1;
                    p_len --;
                    p++;
                    char temp_p[CONF_FILE_MAX_LINE_SIZE], *temp_p1 = temp_p;
                    strcpy(temp_p, p);
                    int i = 0;
                    //去除值字符串两端的字符
                    while(i < strlen(temp_p) && temp_p[i] == ' '){
                        temp_p1++;
                        i++; 
                    }
                    i = strlen(temp_p1) -1;
                    while(i >= 0 && (temp_p1[i] == ' ' || temp_p1[i] == '\n')){

                        temp_p1[i] = '\0';
                        i--;
                    }
                    if(strlen(temp_p1) == 0){
                        value[0] = '\0';
                    }else{
                        strcpy(value, temp_p);
                    }
                    goto success1;
                }
            }
        }
        curr_node = curr_node->next;
    }  
    ret = -1;
success1:
    fclose(pfile);
    curr_node = root_node;
    while(curr_node){    
        pre_node = curr_node;
        curr_node = curr_node->next;
        free(pre_node);
    }
    return ret;
}

2,conf_file.h

#ifndef CONF_FILE_H
#define CONF_FILE_H

/*
***********************************************************
 *函数名:conf_file_set_value_by_key
 *功   能:根据提供的键设置配置文件中的值,如果指定的键不存在,则在最后一行添加
 *输   入:file[in]:配置文件名;key[in]:键-值中的键;symbol[in]:处于键-值之间的的符号,
         该符号必须具备将键-值区别开的能力,即键,值中不能包含该字符;value[in]:键-值中的值
 *输   出:key
 *返回 值:成功返回0,如果返回-1
 *说  明:
 *************************************************************
 */
int conf_file_set_value_by_key(const char *file, const char *key,const char symbol, const char *value);
/*
***********************************************************
 *函数名:conf_file_set_value_by_key
 *功   能:根据提供的键设置配置文件中的值,如果指定的键不存在,则在最后一行添加
 *输   入:file[in]:配置文件名;key[in]:键-值中的键;symbol[in]:处于键-值之间的的符号,
         该符号必须具备将键-值区别开的能力,即键,值中不能包含该字符;value[in]:键-值中的值
 *输   出:key
 *返回 值:成功返回0,如果返回-1
 *说  明:
 *************************************************************
 */
int conf_file_get_value_by_key(const char *file,const  char *key,const char symbol, char *value);

#endif 

3, test.c

#include
#include
#include
#include
#include
#include"conf_file.h"

static void Fork(){
    pid_t temp_pid;
    temp_pid = fork();
    if(temp_pid < 0){
        exit(-1);
    }else if(temp_pid > 0){
        exit(0);
    }
}


int main(int argc, char *argv[]){
    char value[256];
    if(argc > 2) return 0; 
    if(argc == 2){
        if(0 == strcmp("-f", argv[1])){
            Fork();
        }else return -1;
    }
    //

    // if(argv[1]){
    //     if(argv[2]){
    //         conf_file_set_value_by_key("test.ini", argv[1], ':', argv[2]);
    //     }else{
    //         conf_file_set_value_by_key("test.ini", "ip", ':', argv[1]);
    //     }
    // }else{  
    //     conf_file_set_value_by_key("test.ini", "ip", ':', "2345");
    // }
    if(argv[1]){
        conf_file_get_value_by_key("test.ini", argv[1], ':', value);
    }else{  
        conf_file_get_value_by_key("test.ini", "ip", ':', value);
    }
    printf("strlen(value):%lu value:%s\n",strlen(value),value);
    while(1){
        sleep(5);
        printf("%s %s %d\n",__FILE__, __func__, __LINE__);
    }
    return 0;
}

4,Makefile


TARGET=test
OBJECT=test.c conf_file.c
$(TARGET):$(OBJECT)
	gcc -g -Wall $(OBJECT) -o $(TARGET)
clean:
	rm $(TARGET)


5,test.ini

ip:2345

你可能感兴趣的:(配置文件读写工具(c语言实现))