• C读写配置文件


            在项目开发中,经常需要读取应用配置文件的初始化参数,用于应用在启动前进行一些初始化配置。比如:Eclipse,参数项包含主题、字体大小、颜色、Jdk安装位置、自动提示等。Eclispe配置的文件格式是以键值对的方式存储的,即:key=value的形式,下面是Eclipse部份设置参数:

    /instance/org.eclipse.jdt.ui/useQuickDiffPrefPage=true
    /instance/org.eclipse.jdt.ui/content_assist_proposals_foreground=0,0,0
    /instance/org.eclipse.egit.core/GitRepositoriesView.GitDirectories=/Users/yangxin/Downloads/kakaolink-android/.git:/Users/yangxin/Documents/workspace_web/tfyj/.git:
    /instance/org.eclipse.wst.jsdt.ui/fontPropagated=true
    /instance/org.eclipse.debug.core/org.eclipse.debug.core.USE_STEP_FILTERS=true
    /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
    /instance/org.eclipse.ui.workbench/org.eclipse.jface.textfont=1|Monaco|14.0|0|COCOA|1|Monaco;
    @org.eclipse.jdt.ui=3.8.2.v20130107-165834
    /instance/org.eclipse.cdt.ui/spelling_locale_initialized=true
    从Eclipse配置文件中可以看出,都是以xxxx=xxxxx如最后一个配置项,key为/instance/org.eclipse.cdt.ui/spelling_locale_initialized,值为:true。在项目开发当中的也经常采用这种方式,笔者参考了Java的java.util.Properties类,设计了一个C的配置文件读写接口,供大家学习和使用。

    1、定义接口头文件(Properties.h)

    //
    //  Properties.h
    //  读写配置文件
    //
    //  Created by 杨信 on 14-4-24.
    //  Copyright (c) 2014年 yangxin. All rights reserved.
    //
    
    #ifndef _______Properties_h
    #define _______Properties_h
    
    #ifdef _cplusplus
    extern "C" {
    #endif
        
        // 初始化环境,成功返回0,失败返回非0值
        int init(const char *filepath,void **handle);
        
        // 根据KEY获取值,找到返回0,如果未找到返回非0值
        int getValue(void *handle, const char *key, char *value);
        
        // 修改key对应的属性值,修改成功返回0,失败返回非0值
        int setValue(void *handle, const char *key, const char *value);
        
        // 添加一个属性,添加成功返回0,失败返回非0值
        int add(void *handle, const char *key, const char *value);
        
        // 删除一个属性,删除成功返回0,失败返回非0值
        int del(void *handle, const char *key);
        
        // 获取属性文件中所有的key,获取成功返回0,失败返回非0值
        int getKeys(void *handle, char ***keys, int *keyscount);
        
        // 释放所有key的内存空间,成功返回0,失败返回非0值
        int free_keys(char ***keys,int *keyscount);
        
        // 获取属性文件中所有的值,成功返回0,失败返回非0值
        int getValues(void *handle, char ***values, int *valuescount);
        
        // 释放所有value的内存空间,成功返回0,失败返回非0值
        int free_values(char ***values, int *valuescount);
        
        // 获取属性数量,成功返回0,失败返回非0值
        int getCount(void *handle, int *count);
        
        // 释放环境资源,成功返回0,失败返回非0值
        int release(void **handle);
        
        
    #ifdef _cplusplus
    }
    #endif
    
    #endif

    2、实现头文件的接口(Properteis.c)

    //
    //  Properties.c
    //  读写配置文件
    //
    //  Created by 杨信 on 14-4-24.
    //  Copyright (c) 2014年 yangxin. All rights reserved.
    //
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include "Properties.h"
    
    #define KEY_SIZE        128 // key缓冲区大小
    #define VALUE_SIZE      128 // value缓冲区大小
    
    #define LINE_BUF_SIZE   256 // 读取配置文件中每一行的缓冲区大小
    
    typedef struct Properties {
        char *key;
        char *value;
        struct Properties *pNext;
    }Properties;
    
    typedef struct PROPS_HANDLE {
        Properties *pHead;  // 属性链表头节点
        char *filepath;     // 属性文件路径
    }PROPS_HANDLE;
    
    static int createPropsNode(Properties **props);         // 创建一个节点
    static int trimeSpace(const char *src,char *dest);      // 去空格
    static int saveConfig(const char *filepath,Properties *head);   // 将修改或保存后的配置项保存到文件
    
    // 初始化环境,成功返回0,失败返回非0值
    int init(const char *filepath,void **handle)
    {
        int ret = 0;
        FILE *fp = NULL;
        Properties *pHead = NULL,*pCurrent = NULL, *pMalloc = NULL;
        PROPS_HANDLE *ph = NULL;
        char line[LINE_BUF_SIZE];               // 存放读取每一行的缓冲区
        char keybuff[KEY_SIZE] = { 0 };         // 存放key的缓冲区
        char valuebuff[VALUE_SIZE] = { 0 };     // 存放value的缓冲区
        char *pLine = NULL;                     // 每行缓冲区数据的指针
        
        if(filepath == NULL || handle == NULL)
        {
            ret = -1;
            printf("fun init error:%d from (filepath == NULL || handler == NULL)
    ",ret);
            return ret;
        }
        
        ph = (PROPS_HANDLE *)malloc(sizeof(PROPS_HANDLE));
        if (ph == NULL) {
            ret = -2;
            printf("fun init malloc handle error:%d",ret);
            return ret;
        }
        memset(ph, 0, sizeof(PROPS_HANDLE));
        
        // 打开文件
        fp = fopen(filepath, "r");
        if (!fp) {
            ret = -3;
            printf("fun init open file error:%d from %s
    ",ret,filepath);
            return ret;
        }
        
        // 创建头节点
        ret = createPropsNode(&pHead);
        if (ret != 0) {
            fclose(fp);  // 关闭文件
            printf("fun init create head node error:%d
    ",ret);
            return ret;
        }
        memset(pHead, 0, sizeof(Properties));
        
        // 保存链表头节点和文件路径到handle中
        ph->pHead = pHead;
        ph->filepath = (char *)malloc(strlen(filepath) + 1);
        strcpy(ph->filepath, filepath);
        
        pCurrent = pHead;
    
        // 读取配置文件中的所有数据
        while (!feof(fp)) {
            if(fgets(line, LINE_BUF_SIZE, fp) == NULL)
            {
                break;
            }
            
            // 找等号
            if ((pLine = strstr(line, "=")) == NULL) {   // 没有等号,继续读取下一行
                continue;
            }
            
            // 循环创建节点
            ret = createPropsNode(&pMalloc);
            if (ret != 0) {
                fclose(fp);  // 关闭文件
                release((void **)&ph);  // 创建节点失败,释放所有资源
                printf("create new node error:%d
    ",ret);
                return ret;
            }
    
            // 设置Key
            memcpy(keybuff, line, pLine-line);
            trimeSpace(keybuff, pMalloc->key);    // 将keybuff去空格后放到pMallock.key中
        
            // 设置Value
            pLine += 1;
            trimeSpace(pLine, valuebuff);
            strcpy(pMalloc->value, valuebuff);
            
            // 将新节点入链表
            pMalloc->pNext = NULL;
            pCurrent->pNext = pMalloc;
            pCurrent = pMalloc; // 当前节点下移
            
            // 重置key,value
            memset(keybuff, 0, KEY_SIZE);
            memset(valuebuff, 0, VALUE_SIZE);
        }
        
        // 设置环境句柄给调用者
        *handle = ph;
        
        // 关闭文件
        fclose(fp);
        
        return ret;
    }
    
    // 获取属性数量,成功返回0,失败返回非0值
    int getCount(void *handle, int *count)
    {
        int ret = 0,cn = 0;
        PROPS_HANDLE *ph = NULL;
        Properties *pCurrent = NULL;
        if (handle == NULL || count == NULL) {
            ret = -1;
            printf("fun getCount error:%d from (handle == NULL || count == NULL)
    ",ret);
            return ret;
        }
        ph = (PROPS_HANDLE *)handle;
        pCurrent = ph->pHead->pNext;
        while (pCurrent != NULL) {
            cn++;
            pCurrent = pCurrent->pNext;
        }
        
        *count = cn;
        
        return ret;
    }
    
    // 根据KEY获取值,找到返回0,如果未找到返回非0值
    int getValue(void *handle, const char *key, char *value)
    {
        int ret = 0;
        PROPS_HANDLE *ph = NULL;
        Properties *pCurrent = NULL;
        if (handle == NULL || key == NULL || value == NULL) {
            ret = -1;
            printf("getValue error:%d from (handle == NULL || key == NULL || value == NULL)
    ",ret);
            return ret;
        }
        
        ph = (PROPS_HANDLE *)handle;
        pCurrent = ph->pHead->pNext;
        while (pCurrent != NULL) {
            if (strcmp(pCurrent->key,key) == 0) {
                break;
            }
            pCurrent = pCurrent->pNext;
        }
        
        if (pCurrent == NULL) {
            ret = -2;
            printf("fun getValue warning: not found the key:%s
    ",key);
            return ret;
        }
        
        strcpy(value, pCurrent->value);
        
        return ret;
    }
    
    // 修改key对应的属性值,修改成功返回0,失败返回非0值
    int setValue(void *handle, const char *key, const char *value)
    {
        int ret = 0;
        PROPS_HANDLE *ph = NULL;
        Properties *pCurrent = NULL;
        if (handle == NULL || key == NULL || value == NULL) {
            ret = -1;
            printf("fun setValue error:%d from (handle == NULL || key == NULL || value == NULL)
    ",ret);
            return ret;
        }
        
        // 获得环境句柄
        ph = (PROPS_HANDLE *)handle;
        
        // 从环境句柄中获取头节点
        pCurrent = ph->pHead->pNext;
        while (pCurrent != NULL) {
            if (strcmp(pCurrent->key, key) == 0) {  // 找到
                break;
            }
            pCurrent = pCurrent->pNext;
        }
        
        if (pCurrent == NULL) { // 未找到key
            ret = -2;
            printf("fun setValue warning: not found the key:%s
    ",key);
            return ret;
        }
        
        // 修改key的value
        strcpy(pCurrent->value, value);
        if (strchr(value, '
    ') == NULL) {  // 加一个换行符
            strcat(pCurrent->value, "
    ");
        }
        
        // 将修改的配置项写入到文件
        ret = saveConfig(ph->filepath, ph->pHead);
      
        return ret;
    }
    
    // 添加一个属性,添加成功返回0,失败返回非0值
    int add(void *handle, const char *key, const char *value)
    {
        int ret = 0;
        PROPS_HANDLE *ph = NULL;
        Properties *pCurrent = NULL;
        if (handle == NULL || key == NULL || value == NULL) {
            ret = -1;
            printf("fun add error:%d from (handle == NULL || key == NULL || value == NULL)
    ",ret);
            return ret;
        }
        
        ph = (PROPS_HANDLE *)handle;
        
        //-----------如果key存在链表中,则直接修改,否则添加到链表中-----------//
        pCurrent = ph->pHead;
        while (pCurrent->pNext != NULL) {
            if (strcmp(pCurrent->pNext->key,key) == 0) {
                break;
            }
            pCurrent = pCurrent->pNext;
        }
        
        if (pCurrent->pNext != NULL) {
            return setValue(handle, key, value);
        }
        
        //-----------key不存在,创建一个新的配置项,添加到链表中-----------//
        Properties *pMalloc;
        ret = createPropsNode(&pMalloc);
        if (ret != 0) {
            printf("fun add error:%d from malloc new node.",ret);
            return ret;
        }
        
        strcpy(pMalloc->key, key);
        if (strchr(pCurrent->value,'
    ') == NULL) {
            strcat(pCurrent->value, "
    ");
        }
        strcpy(pMalloc->value, value);
        if (strchr(value, '
    ') == NULL) {  // 加一个换行符
            strcat(pMalloc->value, "
    ");
        }
        pCurrent->pNext = pMalloc;  // 新配置项入链表
        
        // 将新配置项写入到文件
        ret = saveConfig(ph->filepath, ph->pHead);
        
        return ret;
    }
    
    // 删除一个属性,删除成功返回0,失败返回非0值
    int del(void *handle, const char *key)
    {
        int ret = 0;
        PROPS_HANDLE *ph = NULL;
        Properties *pCurrent = NULL, *pPrev = NULL;
        if (handle == NULL || key == NULL) {
            ret = -1;
            printf("fun del error:%d from (handle == NULL || key == NULL)
    ",ret);
            return ret;
        }
        
        ph = (PROPS_HANDLE *)handle;
        pPrev = ph->pHead;
        pCurrent = ph->pHead->pNext;
        
        while (pCurrent != NULL) {
            if (strcmp(pCurrent->key, key) == 0) {
                break;
            }
            pPrev = pCurrent;           // 上一个节点下移
            pCurrent = pCurrent->pNext; // 当前节点下移
        }
        
        if (pCurrent == NULL) { // 没有找到
            ret = -2;
            printf("fun del warning:not found the key:%s
    ",key);
            return  ret;
        }
        
        pPrev->pNext = pCurrent->pNext; // 从链表中删除
        free(pCurrent); // 释放内存
        pCurrent = NULL;
        
        // 保存到文件
        ret = saveConfig(ph->filepath, ph->pHead);
        
        return ret;
    }
    
    // 获取属性文件中所有的key,获取成功返回0,失败返回非0值
    int getKeys(void *handle, char ***keys, int *keyscount)
    {
        int ret = 0, count = 0, index = 0;
        PROPS_HANDLE *ph = NULL;
        Properties *pCurrent = NULL;
        char **pKeys = NULL;
        if (handle == NULL || keys == NULL || keyscount == NULL) {
            ret = -1;
            printf("fun getKeys error:%d from (handle == NULL || keys == NULL || keyscount == NULL) 
    ",ret);
            return ret;
        }
        
        // 获取配置项数量
        ret = getCount(handle, &count);
        if (ret != 0) {
            printf("fun getKeys error:%d from getCount 
    ",ret);
            return ret;
        }
        
        ph = (PROPS_HANDLE *)handle;
        pCurrent = ph->pHead->pNext;
        
        // 根据链表长度,申请内存空间
        pKeys = (char **)malloc(sizeof(char *) * count);
        if (pKeys == NULL) {
            ret = -2;
            printf("fun getKeys error:%d from malloc keys
    ",ret);
            return ret;
        }
        
        pCurrent = ph->pHead->pNext;
        while (pCurrent != NULL) {
            pKeys[index] = pCurrent->key;
            pCurrent = pCurrent->pNext;
            index++;
        }
        
        *keys = pKeys;
        *keyscount = count;
        
        return ret;
    }
    
    // 释放所有key的内存空间,成功返回0,失败返回非0值
    int free_keys(char ***keys,int *keyscount)
    {
        int ret = 0;
        if (keys == NULL || keyscount == NULL) {
            ret = -1;
            printf("fun free_keys error:%d from (keys == NULL || keyscount == NULL) 
    ",ret);
            return ret;
        }
        
        free(*keys);
        *keys = NULL;
        *keyscount = 0;
        
        return ret;
    }
    
    // 获取属性文件中所有的值,成功返回0,失败返回非0值
    int getValues(void *handle, char ***values, int *valuescount)
    {
        int ret = 0, count = 0, index = 0;
        PROPS_HANDLE *ph = NULL;
        Properties *pCurrent = NULL;
        char **pValues = NULL;
        if (handle == NULL || values == NULL || valuescount == NULL) {
            ret = -1;
            printf("fun getValues error:%d from (handle == NULL || values == NULL || valuescount == NULL)
    ",ret);
            return ret;
        }
        
        // 获取配置项数量
        ret = getCount(handle, &count);
        if (ret != 0) {
            printf("fun getValues error:%d from getCount 
    ",ret);
            return ret;
        }
        
        // 申请内存空间,存放所有的value
        pValues = (char **)malloc(sizeof(char *) * count);
        if (pValues == NULL) {
            ret = -2;
            printf("fun getValues error:%d from malloc values
    ",ret);
            return ret;
        }
        
        ph = (PROPS_HANDLE *)handle;
        pCurrent = ph->pHead->pNext;
        while (pCurrent != NULL) {
            pValues[index] = pCurrent->value;
            pCurrent = pCurrent->pNext;
            index++;
        }
        
        *values = pValues;
        *valuescount = count;
        
        return ret;
    }
    
    // 释放所有value的内存空间,成功返回0,失败返回非0值
    int free_values(char ***values, int *valuescount)
    {
        int ret = 0;
        if (values == NULL || valuescount == NULL) {
            ret = -1;
            printf("fun free_values error:%d from (values == NULL || valuescount == NULL) 
    ",ret);
            return ret;
        }
        
        free(*values);
        *values = NULL;
        *valuescount = 0;
        
        return ret;
    }
    
    // 释放环境资源,成功返回0,失败返回非0值
    int release(void **handle)
    {
        int ret = 0;
        PROPS_HANDLE *ph = NULL;
        if(handle == NULL)
        {
            ret = -1;
            printf("release error:%d from (handler == NULL)
    ",ret);
            return ret;
        }
        
        ph = (PROPS_HANDLE *)*handle;
        
        // 释放链表内存资源
        Properties *pCurr = ph->pHead;
        Properties *pTemp = NULL;
        
        while (pCurr != NULL) {
            if (pCurr->key != NULL) {
                free(pCurr->key);
                pCurr->key = NULL;
            }
            
            if (pCurr->value != NULL) {
                free(pCurr->value);
                pCurr->value = NULL;
            }
            
            pTemp = pCurr->pNext;
            
            free(pCurr);
            
            pCurr = pTemp;
        }
        
        // 释放存放配置文件路径分配的内存空间
        if(ph->filepath != NULL)
        {
            free(ph->filepath);
            ph->filepath = NULL;
        }
        
        // 释放环境句柄本身
        free(ph);
        *handle = NULL;    // 避免野指针
            
        return ret;
    }
    
    // 去空格
    static int trimeSpace(const char *src,char *dest)
    {
        int ret = 0;
        if (src == NULL || dest == NULL) {
            ret = -1;
            printf("trimeSpace error:%d from (src == NULL || dest == NULL)
    ",ret);
            return ret;
        }
        
        const char *psrc = src;
        unsigned long i = 0,j = strlen(psrc) - 1,len;
        while (psrc[i] == ' ')
        {
            i++;
        }
        
        while (psrc[j] == ' ') {
            j--;
        }
        
        len = j - i + 1;
        
        memcpy(dest,psrc+i,len);
        *(dest+len) = '';
        
        return ret;
    }
    
    // 创建一个节点
    static int createPropsNode(Properties **props)
    {
        int ret = 0;
        Properties *p = NULL;
        if (props == NULL) {
            ret = -100;
            printf("createProps error:%d from (props == NULL)
    ",ret);
            return ret;
        }
        
        p = (Properties *)malloc(sizeof(Properties));
        if (p == NULL) {
            ret = -200;
            printf("createProps malloc %ld bytes error:%d
    ",sizeof(Properties),ret);
            return ret;
        }
        p->key = (char *)malloc(KEY_SIZE);
        p->value = (char *)malloc(VALUE_SIZE);
        p->pNext = NULL;
        
        *props = p;
        
        return ret;
    }
    
    // 保存到文件
    static int saveConfig(const char *filepath,Properties *head)
    {
        int ret = 0,writeLen = 0;
        FILE *fp = NULL;
        Properties *pCurrent = NULL;
        if (filepath == NULL || head == NULL) {
            ret = -100;
            printf("fun saveConfig error:%d from (filepath == NULL || head == NULL)
    ",ret);
            return ret;
        }
        
        fp = fopen(filepath,"w");
        if (fp == NULL) {
            ret = -200;
            printf("fun saveConfig:open file error:%d from %s
    ",ret,filepath);
            return ret;
        }
        
        pCurrent = head->pNext;
        while (pCurrent != NULL) {
            writeLen = fprintf(fp, "%s=%s",pCurrent->key,pCurrent->value);    // 返回写入的字节数,出现错误返回一个负值
            if (writeLen < 0) {  //TODO 如果写入失败,如何将写入的数据回退???
                ret = -300;
                printf("fun saveConfig err:%d from (%s=%s)
    ",ret,pCurrent->key,pCurrent->value);
                break;
            }
            pCurrent = pCurrent->pNext;
        }
    
        fclose(fp); // 关闭文件
        
        return ret;
    }
    

    3、测试代码(需要在项目根目录创建props.txt)

    //
    //  main.c
    //  读写配置文件
    //
    //  Created by 杨信 on 14-4-24.
    //  Copyright (c) 2014年 yangxin. All rights reserved.
    //
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "Properties.h"
    
    int main(int argc, const char * argv[])
    {
        int ret;
        void *handle;
        const char *filepath = "/Users/yangxin/Desktop/props.txt";
        // 初始化
        ret = init(filepath, &handle);
        if (ret != 0) {
            printf("env init error:%d
    ",ret);
            return 0;
        }
        
        char valuebuf[128];
        // 测试获取配置项
        ret = getValue(handle, "host", valuebuf);
        if (ret == 0) {
            printf("value=%s
    ",valuebuf);
        }
        else {
            printf("获取值host的值失败
    ");
        }
        
        // 测试修改配置项
        ret = setValue(handle, "version", "1.2.3");
        if (ret == 0) {
            printf("修改成功!
    ");
        }
        else{
            printf("修改失败
    ");
        }
        
        // 测试添加配置项
        ret = add(handle, "pool_connection_countxx", "2000");
        if (ret == 0) {
            printf("添加成功!
    ");
        }
        else{
            printf("添加失败
    ");
        }
        
        // 测试删除配置项
        ret = del(handle, "connectionMax");
        if (ret == 0) {
            printf("删除成功!
    ");
        }
        else{
            printf("删除失败
    ");
        }
        
        // 测试获取所有配置项的key
        char **keys = NULL;
        int keyscount;
        ret = getKeys(handle, &keys, &keyscount);
        if (ret == 0) {
            printf("一共有%d个Key
    ",keyscount);
            for (int i =0; i<keyscount; i++) {
                printf("%s
    ",keys[i]);
            }
        }
        // 释放内存
        ret = free_keys(&keys, &keyscount);
        if (ret == 0) {
            printf("keys释放内存成功!
    ");
        }
        
        // 测试获取所有配置项的value
        char **values = NULL;
        int valuescount;
        ret = getValues(handle, &values, &valuescount);
        if (ret == 0) {
            printf("一共有%d个Value
    ",valuescount);
            for (int i = 0; i < valuescount; i++) {
                printf("%s",values[i]);
            }
        }
        // 释放内存
        ret = free_values(&values, &valuescount);
        if (ret == 0) {
            printf("values释放内存成功!
    ");
        }
        
        // 释放资源
        ret = release(&handle);
        if (ret != 0) {
            printf("env release error:%d
    ",ret);
        }
        
        return 0;
    }
    

    测试配置文件:

    username=root
    password=root123456
    host=192.168.1.100
    port=9090
    connectionMax=200
    version=1.0

    测试结果:

    源码下载地址:git@github.com:xyang0917/RWAppProperites.git

  • 相关阅读:
    loadrunder之脚本篇——集合点设置
    Loadrunner之脚本篇——事务函数
    Loadrunder之脚本篇——事务时间简介
    Loadrunder之脚本篇——参数化在场景中的运用
    Java提高(一)---- HashMap
    阅读收集
    SpringMVC是什么?
    elasticsearch head安装
    Elasticsearch 全量遍历数据
    JVM 堆内存,参数优化
  • 原文地址:https://www.cnblogs.com/xyang0917/p/4172504.html
Copyright © 2020-2023  润新知