在Linux/openwrt等嵌入式系统中,使用到了大量配置文件,比如硬件配置,系统配置,应用程序
配置。这些配置信息通常都是以文本文件为载体,以键值对的形式存储于本地或远程文件系统中。
可以参考openwrt的uci命令系统,简易的自定义自己程序的配置文件解析,方便于在命令行或
应用程序内部即时读写配置参数。
config_file_rw.c
/**
create by iversondeng168
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#define DEBUG
#define CONFIG_FILE "./etc/config_file_rw.conf"
//键值对结构体
typedef struct item_t {
char *key;
char *value;
}ITEM;
//去除一行字符串右边的空格
char *str_trim_right(char *pstr)
{
int i;
i = strlen(pstr) - 1;
while (isspace(pstr[i]) && i >= 0)
pstr[i--] = 0;
return pstr;
}
//去除一行字符串左边的空格
char *str_trim_left(char *pstr)
{
int i = 0,j = 0;
j = strlen(pstr) - 1;
while (isspace(pstr[i]) && (i <= j))
i++;
if (0 < i)
strcpy(pstr, &pstr[i]);
return pstr;
}
//同时去除字符串左右两边的空格
char *str_trim(char *pstr)
{
char *p;
p = str_trim_right(pstr);
return str_trim_left(p);
}
//从一行字符串中解析出键值对
int get_item_from_line(char *line, ITEM *item)
{
char *pline = str_trim(line);
int len = strlen(pline);
if(len <= 0)
{
return -1;
}
else if(pline[0]=='#' || pline[0]=='/')
{
return -2;
}
else
{
char *p = strchr(pline, '=');
*p++ = 0;
item->key = (char *)malloc(strlen(pline) + 1);
item->value = (char *)malloc(strlen(p) + 1);
pline = str_trim(pline);
p = str_trim(p);
strcpy(item->key,pline);
strcpy(item->value,p);
}
return 0;
}
//将整个配置文件解析出键值对数组保存在内存中
int file_to_items(const char *filename, ITEM *items, int *num)
{
char line[1024];
FILE *fp;
fp = fopen(filename,"r");
if(fp == NULL)
return 1;
int i = 0;
int len = 0;
char*p1 = NULL;
char*p2 = NULL;
while(fgets(line, 1024 - 1, fp))
{
p1 = str_trim(line);
len = strlen(p1);
if(len <= 0)
{
continue;
}
else if(p1[0]=='#')
{
continue;
}
else
{
p2 = strchr(p1, '=');
if(p2 == NULL)
continue;
*p2++ = 0;
items[i].key = (char *)malloc(strlen(p1) + 1);
items[i].value = (char *)malloc(strlen(p2) + 1);
p1 = str_trim(p1);
p2 = str_trim(p2);
strcpy(items[i].key,p1);
strcpy(items[i].value,p2);
i++;
}
}
*num = i;
fclose(fp);
return 0;
}
//从配置文件中读取指定键的值
int read_conf_value(const char *filename,char *key,char *value)
{
char line[1024];
FILE *fp;
ITEM item;
fp = fopen(filename,"r");
if(fp == NULL)
return -1;
while (fgets(line, 1024-1, fp))
{
if(get_item_from_line(line,&item))
{
continue;
}
if(!strcmp(item.key,key))
{
strcpy(value,item.value);
free(item.key);
free(item.value);
fclose(fp);
return 0;
}
}
fclose(fp);
return -2;
}
//向配置文件中写入指定键的值
int write_conf_value(const char *filename,char *key,char *value)
{
ITEM items[1024];
int num;
//将文件的键值对加载到内存
file_to_items(filename, items, &num);
int i=0;
//修改指定键值
for(i=0;i<num;i++)
{
if(!strcmp(items[i].key, key))
{
items[i].value = value;
break;
}
}
if(i >= num)
{
return -1;
}
//同步到文件
FILE *fp;
fp = fopen(filename, "w");
if(fp == NULL)
{
return -2;
}
for(i=0;i<num;i++)
{
fprintf(fp,"%s=%s\n",items[i].key, items[i].value);
}
fclose(fp);
return 0;
}
/**eg.
config_file_rw -r A1
config_file_rw -r B2
config_file_rw -w C3 test
*/
int main(int argc,char*argv[])
{
char tmpdata[128] = {0};
int retval;
if(3 != argc && 4 != argc)
{
#ifdef DEBUG
printf("not support!\n");
#endif
return -1;
}
if(3 == argc)
{
if(strcmp(argv[1],"-r"))
{
#ifdef DEBUG
printf("argv[1] must -r!\n");
#endif
return -2;
}
retval = read_conf_value((const char*)CONFIG_FILE,argv[2],tmpdata);
if(retval)
{
switch(retval)
{
case 0:
break;
case -1:
#ifdef DEBUG
printf("read error!\n");
#endif
break;
case -2:
#ifdef DEBUG
printf("not found!\n");
#endif
break;
}
return -3;
}
printf("%s",tmpdata);
}
else
{
if(strcmp(argv[1],"-w"))
{
#ifdef DEBUG
printf("argv[1] must -w!\n");
#endif
return -4;
}
strcpy(tmpdata,argv[3]);
retval = write_conf_value((const char*)CONFIG_FILE,argv[2],tmpdata);
if(retval)
{
switch(retval)
{
case 0:
break;
case -1:
#ifdef DEBUG
printf("not found!\n");
#endif
break;
case -2:
#ifdef DEBUG
printf("write error!\n");
#endif
break;
}
return -5;
}
}
return 0;
}
测试配置文件./etc/config_file_rw.conf
A1=one
B2=two
C3=three
执行交叉编译
/home/source/prebuilt/gcc/linux-x86/arm/toolchain-sunxi-musl/toolchain/bin/arm-openwrt-linux-gcc config_file_rw.c -o config_file_rw -O2 -w