詳解C語(yǔ)言如何實(shí)現(xiàn)配置文件的讀寫
C語(yǔ)言實(shí)現(xiàn)配置文件的讀寫
| 文件名 | 作用 |
|---|---|
| global.h | 定義一些宏 |
| Func.h | 公用函數(shù)頭文件 |
| Func.c | 公用函數(shù)的實(shí)現(xiàn) |
| config.h | 讀寫配置文件的函數(shù)聲明 |
| config.c | 讀寫配置文件的函數(shù)實(shí)現(xiàn) |
| config_main.c | 主函數(shù)入口 |
| config.conf | 配置文件 |
直接上代碼,一些解釋以注釋的形式寫在了相應(yīng)的文件里面。
// 文件名: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兩個(gè)字符串內(nèi)容是否一樣,忽略大小寫的比較 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; //此時(shí)p_tmp指向了sstring
if ((*p_tmp) != ' ')
return; //不是以空格開頭
//找到第一個(gè)不為空格的位置
while ((*p_tmp) != '\0')
{
if ((*p_tmp) == ' ')
p_tmp++;
else
break;
}
if ((*p_tmp) == '\0') //全是空格
{
*sstring = '\0';
return;
}
char *p_tmp2 = sstring; //此時(shí) p_tmp2 指向了 sstring
while ((*p_tmp) != '\0')
{
(*p_tmp2) = (*p_tmp);
p_tmp++;
p_tmp2++;
}
(*p_tmp2) = '\0'; //空格處理完畢,記得在末尾添加一個(gè)'\0' 表示字符串結(jié)尾
return;
}
//比較str1和str2兩個(gè)字符串內(nèi)容是否一樣,忽略大小寫的比較
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的內(nèi)容拷貝到str中
StringCase(str); //把str中的所有內(nèi)容轉(zhuǎn)成大寫字母
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數(shù)組的大小,也是配置文件中有效的item項(xiàng)目的最大值
#define CONFIGSTRUCTSIZE 80
#define CONFIGNAMESIZE 32
#define CONFIGCONTENTSIZE 512
struct ConfigStruct{
char ItemName[CONFIGNAMESIZE];
char ItemContent[CONFIGCONTENTSIZE];
};
// 加載配置文件
int LoadConfigFile(const char* pconfName);
// 通過item名字獲取item的內(nèi)容
const char* GetConfigFromString(const char* p_itemname);
// 通過item名字獲取item內(nèi)容,整型,獲取不到返回默認(rèn)值
int GetConfigIntDefault(const char* p_itemname, const int def);
// // 釋放內(nèi)存
// void FreeConfigItem();
// 寫配置文件
// 通過item名字修改item內(nèi)容
int ModifyConfigItemContent(const char* p_itemName, const char* p_itemContent);
// 通過item名字和內(nèi)容 添加新的item項(xiàng)目
int AddConfigItem(const char*p_itemName, const char* p_itemContent);
// 把加載進(jìn)來(lái)的、或者有修改過了、增加過的 item數(shù)組寫到指定的文件
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;
// 每一行配置文件讀取出來(lái)放到這里
unsigned int linebuf_size = CONFIGCONTENTSIZE + 1 + CONFIGNAMESIZE + 1 + 1;
char linebuf[linebuf_size]; // 128+1 結(jié)尾為結(jié)束符
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 == '[') // [ 開頭的注釋,也保存,方便以后寫文件時(shí)寫回去
{
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;
}
// 到這里,都是合法的配置項(xiàng)
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
[服務(wù)器地址] 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 [設(shè)備信息] device_id=20210830_1400_00001 device_name=DEV_001 [設(shè)備證書] certificate=CONFIG_BRKZH.GITHUB.IO_CONFIG [設(shè)備是否注冊(cè)] registry_flag=0 CT=65534
把以上的代碼都存到 對(duì)應(yīng)文件 里面,并且放到 同一個(gè)目錄 下。
編譯指令:gcc -o my_conf config_main.c config.c Func.c -I ./
運(yùn)行指令:./my_config
運(yùn)行結(jié)果:

注意:此份代碼僅供學(xué)習(xí)使用,并沒有什么商業(yè)價(jià)值。
因?yàn)檫@段代碼
// item數(shù)組的大小,也是配置文件中有效的item項(xiàng)目的最大值
#define CONFIGSTRUCTSIZE 80
#define CONFIGNAMESIZE 32
#define CONFIGCONTENTSIZE 512
struct ConfigStruct{
char ItemName[CONFIGNAMESIZE];
char ItemContent[CONFIGCONTENTSIZE];
};
static struct ConfigStruct ArrayConfig[CONFIGSTRUCTSIZE];
這里設(shè)定了配置文件的最大項(xiàng)目數(shù)量等,一開始就創(chuàng)建這么多數(shù)組,用于保存配置文件,這些開銷都是在棧上。沒有使用malloc動(dòng)態(tài)分配內(nèi)存,所以代碼僅供學(xué)習(xí)。
到此這篇關(guān)于詳解C語(yǔ)言如何實(shí)現(xiàn)配置文件的讀寫的文章就介紹到這了,更多相關(guān)C語(yǔ)言讀寫配置文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java string對(duì)象上的操作,常見的用法你知道嗎
今天給大家?guī)?lái)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著Java String類用法展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-08-08
c++中移動(dòng)語(yǔ)義和完美轉(zhuǎn)發(fā)及易錯(cuò)點(diǎn)
C++ 中的移動(dòng)語(yǔ)義和完美轉(zhuǎn)發(fā)是 C++11 引入的兩個(gè)重要特性,它們分別用于提高性能和靈活性,這篇文章主要介紹了c++中移動(dòng)語(yǔ)義和完美轉(zhuǎn)發(fā),需要的朋友可以參考下2023-09-09

