首页 > 代码库 > C读写配置文件

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)\n",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\n",ret,filepath);
        return ret;
    }
    
    // 创建头节点
    ret = createPropsNode(&pHead);
    if (ret != 0) {
        fclose(fp);  // 关闭文件
        printf("fun init create head node error:%d\n",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\n",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)\n",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 =http://www.mamicode.com/= NULL) {>

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\n",ret);
        return 0;
    }
    
    char valuebuf[128];
    // 测试获取配置项
    ret = getValue(handle, "host", valuebuf);
    if (ret == 0) {
        printf("value=http://www.mamicode.com/%s/n",valuebuf);>
测试配置文件:

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

测试结果:

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

C读写配置文件