C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C语言读写配置文件

详解C语言如何实现配置文件的读写

作者:布鲁克的小溪流

这篇文章主要为大家详细介绍了如何使用C语言实现配置文件的读写,包括定义全局宏、公用函数、比较字符串等功能,需要的可以参考一下

C语言实现配置文件的读写

文件名作用
global.h定义一些宏
Func.h公用函数头文件
Func.c公用函数的实现
config.h读写配置文件的函数声明
config.c读写配置文件的函数实现
config_main.c主函数入口
config.conf配置文件

直接上代码,一些解释以注释的形式写在了相应的文件里面。

// 文件名:global.h
#ifndef __GLOBAL_H__
#define __GLOBAL_H__
#define bool int
#define false 0
#define true 1

#endif // !__GLOBAL_H__
// 文件名:Func.h
#ifndef __Func_h__
#define __Func_h__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "global.h"

void Rtrim(char* sstring);
void Ltrim(char* sstring);

//比较str1和str2两个字符串内容是否一样,忽略大小写的比较
bool StrcaseCmp(const char* str1, const char* str2);

//把str全都变成大写
void StringCase(char* str);

#endif // !__Func_h__
// 文件名:Func.c
#include "Func.h"

//截取字符串尾部空格
void Rtrim(char *sstring)
{
	size_t len = 0;
	if (sstring == NULL)
		return;
	len = strlen(sstring);
	while (len > 0 && sstring[len - 1] == ' ')//位置换一下
		sstring[--len] = 0;
}

//截取字符串首部空格
void Ltrim(char *sstring)
{
	size_t len = 0;
	if (sstring == NULL)
		return;
	char *p_tmp = sstring;  //此时p_tmp指向了sstring
	if ((*p_tmp) != ' ')
		return;  //不是以空格开头

	//找到第一个不为空格的位置
	while ((*p_tmp) != '\0')
	{
		if ((*p_tmp) == ' ')
			p_tmp++;
		else
			break;
	}
	if ((*p_tmp) == '\0') //全是空格
	{
		*sstring = '\0';
		return;
	}
	char *p_tmp2 = sstring;  //此时 p_tmp2 指向了 sstring
	while ((*p_tmp) != '\0')
	{
		(*p_tmp2) = (*p_tmp);
		p_tmp++;
		p_tmp2++;
	}
	(*p_tmp2) = '\0';  //空格处理完毕,记得在末尾添加一个'\0' 表示字符串结尾
	return;
}

//比较str1和str2两个字符串内容是否一样,忽略大小写的比较
bool StrcaseCmp(const char* str1, const char* str2)
{
	if (str1 == NULL || str2 == NULL)
		return false;
	size_t strLen1 = strlen(str1);
	size_t strLen2 = strlen(str2);
	if (strLen1 != strLen2)
		return false;
	// char *str = new char[strLen2]; 
    char *str = (char*)malloc(strLen2);
	strcpy(str, str2); //把str2的内容拷贝到str中
	StringCase(str);  //把str中的所有内容转成大写字母
	while ((*str) != '\0')
	{
		if ((*str1) > 90)
		{
			if (((*str1) - 32) == (*str))
			{
				++str1;
				++str;
			}
			else {
				return false;
			}
		}
		else {
			if ((*str1) == (*str))
			{
				++str1;
				++str;
			}
			else {
				return false;
			}
		}
	}
    free(str);
	return true;
}

//把str中所有的小写字母变成大写
void StringCase(char* str)
{
	if (str == NULL)
		return ;
	if (strlen(str) <= 0)
		return ;
	int strLen = strlen(str);
	char *ptmp = str;
	while ((*ptmp) != '\0')
	{
		if ((97 <= (*ptmp)) && ((*ptmp) <= 122))
		{
			(*ptmp) -= 32;
		}
		++ptmp;
	}
	return;
}
// 文件名:config.h
#ifndef __CONFIG_H__
#define __CONFIG_H__

#include "global.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Func.h"
#include <fcntl.h>
#include <unistd.h>

// item数组的大小,也是配置文件中有效的item项目的最大值
#define CONFIGSTRUCTSIZE 80
#define CONFIGNAMESIZE 32
#define CONFIGCONTENTSIZE 512

struct ConfigStruct{
    char ItemName[CONFIGNAMESIZE];
    char ItemContent[CONFIGCONTENTSIZE];
};

// 加载配置文件
int LoadConfigFile(const char* pconfName);
// 通过item名字获取item的内容
const char* GetConfigFromString(const char* p_itemname);
// 通过item名字获取item内容,整型,获取不到返回默认值
int GetConfigIntDefault(const char* p_itemname, const int def);

// // 释放内存
// void FreeConfigItem();

// 写配置文件
// 通过item名字修改item内容
int ModifyConfigItemContent(const char* p_itemName, const char* p_itemContent);
// 通过item名字和内容 添加新的item项目
int AddConfigItem(const char*p_itemName, const char* p_itemContent);
// 把加载进来的、或者有修改过了、增加过的 item数组写到指定的文件
int WriteNewConfigFile(const char*pconfName);

#endif // !__CONFIG_H__
// 文件名:config.c
#include <config.h>

static int arr_curr_ind = 0;
static struct ConfigStruct ArrayConfig[CONFIGSTRUCTSIZE];

int LoadConfigFile(const char* pconfName)
{
    if(arr_curr_ind > 0){
        return 0;
    }
    FILE *fp;
    fp = fopen(pconfName, "r");
    if(fp == NULL)
        return false;

    // 每一行配置文件读取出来放到这里
    unsigned int linebuf_size = CONFIGCONTENTSIZE + 1 + CONFIGNAMESIZE + 1 + 1;
    char linebuf[linebuf_size];  // 128+1 结尾为结束符
    memset(linebuf, 0, sizeof(linebuf));
    while(!feof(fp))
    {
        if(fgets(linebuf, linebuf_size, fp) == NULL)
            continue;
        if(linebuf[0] == 0)
            continue;
        if(*linebuf == ';' || *linebuf == ' ' || *linebuf == '#' || *linebuf == '\t' || *linebuf == '\n')
            continue;

        // 去除字符串中的 \r \n 以及空格' '
    lblprocstring:
        if(strlen(linebuf) > 0)
        {
            if(linebuf[strlen(linebuf) - 1] == 10 || linebuf[strlen(linebuf) - 1] == 13 || linebuf[strlen(linebuf) - 1] == 32 )
            {
                linebuf[strlen(linebuf) - 1] = 0;
                goto lblprocstring;
            }
        }
        if(linebuf[0] == 0)
            continue;

        if(*linebuf == '[')  // [ 开头的注释,也保存,方便以后写文件时写回去
        {
            if(arr_curr_ind < CONFIGSTRUCTSIZE)
            {
                strcpy(ArrayConfig[arr_curr_ind].ItemName, linebuf);
                strcpy(ArrayConfig[arr_curr_ind].ItemContent, " ");
                // ArrayConfig[arr_curr_ind] = p_configitem;
                arr_curr_ind += 1;
            }
            else
            {
                // ERROR
            }
            continue;
        }

        // 到这里,都是合法的配置项
        char *ptmp = strchr(linebuf, '=');
        if(ptmp != NULL)
        {
            if(arr_curr_ind < CONFIGSTRUCTSIZE)
            {
                strncpy(ArrayConfig[arr_curr_ind].ItemName, linebuf, (int)(ptmp-linebuf));
                strcpy(ArrayConfig[arr_curr_ind].ItemContent, ptmp+1);
                Rtrim(ArrayConfig[arr_curr_ind].ItemName);
                Ltrim(ArrayConfig[arr_curr_ind].ItemName);
                Rtrim(ArrayConfig[arr_curr_ind].ItemContent);
                Ltrim(ArrayConfig[arr_curr_ind].ItemContent);
                arr_curr_ind += 1;
            }
            else
            {
                // ERROR
            }
        } // end if
    } // end while
    fclose(fp);
    return 1;
}

const char* GetConfigFromString(const char* p_itemname)
{
    int i = 0;
    for(i = 0; i < arr_curr_ind; i++)
    {
        if(strcmp(p_itemname, ArrayConfig[i].ItemName) == 0)
        {
            return ArrayConfig[i].ItemContent;
        }
    }
    return NULL;
}

int GetConfigIntDefault(const char* p_itemname, const int def)
{
    int i;
    for(i = 0; i < arr_curr_ind; i++)
    {
        if(strcmp(p_itemname, ArrayConfig[i].ItemName) == 0)
        {
            return atoi(ArrayConfig[i].ItemContent);
        }
    }
    return def;
}


int ModifyConfigItemContent(const char* p_itemName, const char* p_itemContent)
{
    if (!p_itemName || !p_itemContent)
        return 0;
    int ret_res = 0;
    int i = 0;
    for(i = 0; i < arr_curr_ind; i++)
    {
        if(strcmp(p_itemName, ArrayConfig[i].ItemName) == 0)
        {
            strcpy(ArrayConfig[i].ItemContent, p_itemContent);
            ret_res = 1;
        }
    }
    return ret_res;
}

int AddConfigItem(const char*p_itemName, const char* p_itemContent)
{
    if (!p_itemName || !p_itemContent)
        return 0;
    int i;
    int ret_res = 0;
    for(i=0; i<arr_curr_ind; ++i)
    {
        ret_res = ModifyConfigItemContent(p_itemName, p_itemContent);
        if(ret_res == 1)
            return ret_res;
    }
    ret_res = 0;
    if(arr_curr_ind < CONFIGSTRUCTSIZE)
    {
        strcpy(ArrayConfig[arr_curr_ind].ItemName, p_itemName);
        strcpy(ArrayConfig[arr_curr_ind].ItemContent, p_itemContent);
        arr_curr_ind += 1;
        ret_res = 1;
    }
    else
    {
        ret_res = 0;
    }
    return ret_res;
}

int WriteNewConfigFile(const char*pconfName)
{
    if(!pconfName)
        return 0;
    int new_fd;
    if(-1 == (new_fd = open(pconfName,O_RDWR|O_CREAT|O_TRUNC,0664)))
    {
        return 0;
    }
    int i = 0;
    char line_buf[32+128+1] = "\0";
    char equal_char = '=';
    for(i=0; i < arr_curr_ind; i++)
    {
        if(*(ArrayConfig[i].ItemName) == '[')
            equal_char = ' ';
        else
            equal_char = '=';
        sprintf(line_buf, "%s%c%s\n", ArrayConfig[i].ItemName, equal_char, ArrayConfig[i].ItemContent);
        write(new_fd, line_buf, strlen(line_buf));
        memset(line_buf, 0, sizeof(line_buf));
    }
    close(new_fd);
    return 1;
}
// 文件名:config_main.c
#include "global.h"
#include "config.h"
#include "Func.h"
#include <time.h>

int main()
{
    const char* config_file = "./config.conf";

    LoadConfigFile(config_file);
    const char *ip = GetConfigFromString("server_url");
    const int port = GetConfigIntDefault("server_port", 80);
    if (ip)
        printf("url:%s\t", ip);
    printf("port:%d\n", port);
    printf("device_id:%s\n", GetConfigFromString("device_id"));
    printf("device_name:%s\n", GetConfigFromString("device_name"));
    printf("serv_pub_info_url=%s\n", GetConfigFromString("serv_pub_info_url"));
    printf("serv_pub_curr_log=%s\n", GetConfigFromString("serv_pub_curr_log"));
    printf("serv_pub_hist_log=%s\n", GetConfigFromString("serv_pub_hist_log"));
    printf("certificate=%s\n", GetConfigFromString("certificate"));

    return 0;
}

文件名:config.conf

[服务器地址]  
server_url=192.168.137.1
server_port=80
[信息推送地址]  
serv_regi_dev_url=/regist_dev
serv_pub_info_url=/pub_dev_info
serv_pub_curr_log=/pub_current_log
serv_pub_hist_log=/pub_history_log
[设备信息]  
device_id=20210830_1400_00001
device_name=DEV_001
[设备证书]  
certificate=CONFIG_BRKZH.GITHUB.IO_CONFIG
[设备是否注册]  
registry_flag=0
CT=65534

把以上的代码都存到 对应文件 里面,并且放到 同一个目录 下。

编译指令:gcc -o my_conf config_main.c config.c Func.c -I ./

运行指令:./my_config

运行结果:

注意:此份代码仅供学习使用,并没有什么商业价值。

因为这段代码

// item数组的大小,也是配置文件中有效的item项目的最大值
#define CONFIGSTRUCTSIZE 80
#define CONFIGNAMESIZE 32
#define CONFIGCONTENTSIZE 512

struct ConfigStruct{
    char ItemName[CONFIGNAMESIZE];
    char ItemContent[CONFIGCONTENTSIZE];
};

static struct ConfigStruct ArrayConfig[CONFIGSTRUCTSIZE];

这里设定了配置文件的最大项目数量等,一开始就创建这么多数组,用于保存配置文件,这些开销都是在栈上。没有使用malloc动态分配内存,所以代码仅供学习。

到此这篇关于详解C语言如何实现配置文件的读写的文章就介绍到这了,更多相关C语言读写配置文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文