最近做一个项目,就是嵌入式网页,用到了配置文件,总结来讲就是对配置文件的读写操作,在网上找了半天却发现很少有人写这类相关的,最后我自己尝试着做,而且可以很容易扩展;
首先说一下架构,底层用cgi,上层用js的ajax请求,获取json数据,这个json是cgi实现的,所以cgi需要对配置文件进行读写!
为了以后可以翻出来看一看,也可以帮助有需要的同学参考一下,所以记录下来;
配置文件如下:配置文件说明每一行的长度必须大于你所写字符串的长度,也就是后面应该有一些空格来占位
#set.conf
#devicename
dnm=Mylove
#use name
unm=buer
#Available memory
am=1.5G
#Manufacturer
om=SurperMan
#Serial Number
sn=2014040404
#Product ID
pi=rplay
#Firmware Version
fv=V1.0.2.0
#adv页面
#IP
ip=192.168.100.10
#subnet mask
sm=255.100.223.256
#gateway
gt=192.168.100.111
#setup 页面
#button value
bv=1
#mode select
ms=1
#file name
l1f0=2014314.dmx,2000
l1f1=2014412.dmx,2000
l1f2=2014422.dmx,1000
l1f3=
l1f4=
l1f5=
l1f6=
上面这些文件主要保存的是网页所需要的配置参数;
读取配置文件的代码如下:
文件名为read.c
主要用到的函数有
int sscanf(const char *buffer,const char *format,[argument ]...);
sscanf主要是用来分割字符串,例如:
sscanf( buf, "%[^=]", buf1); 取buf中的字符到=号结束存于buf1中
sscanf( buf, "%*[^=]=%[^ ]", buf2);//通配符取=到空格字符串存于buf2中,这样就将等号左右两边的字符串取出来
char *strtok(char s[], const char *delim);
trtok()用来将字符串分割成一个个片段。参数s指向欲分割的字符串,参数delim则为分割字符串中包含的所有字符。当strtok()在参数s的字符串中发现参数delim中包含的分割字符时,则会将该字符改为\0 字符。在第一次调用时,strtok()必需给予参数s字符串,往后的调用则将参数s设置成NULL。每次调用成功则返回指向被分割出片段的指针。
extern char *strcat(char *dest,char *src);
strcat主要用于两个字符串的拼接
strcpy主要用于两个字符串的拷贝;
#include
#include
#include
#define FLAGYES 1
#define FLAGNO 2
char* createjson(char buf1[],char buf2[],int t);
int cgiMain(){
FILE *fp;
char buf[50];
char buf1[10];
char buf2[40];
char jsonbuf[1024];
char minijson[100];
char filejson[666];
char *tm;
char *token;
char *seps = ",";
int file_flag = 0;
memset(jsonbuf,0,1024);
memset(minijson,0,100);
memset(filejson,0,666);
jsonbuf[0]='{';
minijson[0]='[';
filejson[0]='[';
cgiHeaderContentType("text/html");
fp = fopen("set.conf","rw+");
if (fp==NULL)
{
fputs ("File error",stderr);
exit (1);
}
while ((fgets (buf, 50, fp)) != NULL) //逐行读取文件
{
if((buf[0]=='#')||(buf[0]=='\r')||(buf[0]==' ')||(buf[0]=='\n')) //遇到#,换行符,空格或者换行符就直接跳出本次while循环
{
continue;
}
memset(buf1,0,10); //对数组进行清零操作
memset(buf2,0,40);
sscanf( buf, "%[^=]", buf1); //将buf中的等号前面的字符串取出来存在buf1中
sscanf( buf, "%*[^=]=%[^ ]", buf2);//通配符 取=到空格为止的字符串存于buf2中
if((buf[0]=='l')&&(buf[2]=='f'))//说明这一行为文件列表 l代表list f代表文件 /*此if主要用来讲文件类表中的键值对生成json的格式*/
{
if(buf2[0]!='\0')
{
file_flag = 1;
strcat(buf2,",");
strcat(buf2,buf1);
tm = createjson("u",buf2,FLAGYES);
strcat(filejson,"{");
strcat(filejson,tm);
strcat(filejson,"},");
}
}
else
{
if((strstr(buf2,",")!=NULL)) //字符串中包含空格,数组 /*此处if中主要功能是将buf2中带有,号分割的几组值分割也变为json的格式*/
{
token = strtok(buf2, seps );
while( token != NULL )
{
tm = createjson("u",token,FLAGYES);
strcat(minijson,"{");
strcat(minijson,tm);
strcat(minijson,"},");
token = strtok( NULL, seps);
}
minijson[strlen(minijson)-1]=']';
tm = createjson(buf1,minijson,FLAGNO);
memset(minijson,0,100);
minijson[0]='[';
}
else
{
tm = createjson(buf1,buf2,FLAGYES);
}
strcat(jsonbuf,tm);
strcat(jsonbuf,",");
}
}
if(file_flag==1) //有文件存在 主要是对json格式的封装
{
filejson[strlen(filejson)-1]=']';
tm = createjson("lf",filejson,FLAGNO);
strcat(jsonbuf,tm);
jsonbuf[strlen(jsonbuf)]='}';
}
else
{
jsonbuf[strlen(jsonbuf)-1]='}';
}
printf("%s\n",jsonbuf);
fclose(fp);
}
char* createjson(char buf1[],char buf2[],int t){ //函数的功能也是讲buf1与buf2的值进行键值对的封装为json格式
char tmpbuf[666];
memset(tmpbuf,0,666);
char *rebuf;
char *ma="\"";
char *ta=":";
strcpy(tmpbuf,ma);
strcat(tmpbuf,buf1);
strcat(tmpbuf,ma);
strcat(tmpbuf,ta);
if(t==FLAGYES)
{
strcat(tmpbuf,ma);
strcat(tmpbuf,buf2);
strcat(tmpbuf,ma);
}
else
{
strcat(tmpbuf,buf2);
}
rebuf = tmpbuf;
return rebuf;
}
最后printf出的json数据链为
{"dnm":"Myloveqqq","unm":"buer","am":"1.5G","om":"SurperMan","sn":"2014040404","pi":"rplay","fv":"V1.0.2.0","ip":"192.168.100.10","sm":"255.100.223.256","gt":"192.168.100.111","crf":"womende","bv":"3","ms":"1","prs":"1","as":"2","ps":[{"u":"1"},{"u":"1"},{"u":"1"},{"u":"1"}],"us":[{"u":"6"},{"u":"15"},{"u":"13"},{"u":"14"}],"time":"00:00:00","mp":"1","mf":"1","lf":[{"u":"2014314.dmx"},{"u":"2014412.dmx"},{"u":"2014422.dmx"}]}
上面为json格式数据;
然后网页这边利用Ajax接受这些数据,可以用于监控和数据更新
Ajax代码如下:
$.ajax({
type: "GET",
url: "cgi-bin/read",
cache:false,
dataType: "json",
success:function(data){
obj_data = data;//此时data也就是上面json所代表的数据链;
}
});
取值可以用 data.dnm也就是Myloveqqq data.ps[i].u 也就是表示子结构中的值,以此类推;
其实对配置文件的读写还有一种方法是讲所有的数据读出来以后,存在一个大的缓存中,然后进行操作后再全部写入文件,这种方式也尝试过,但是觉得有欠缺,希望各位大神有好的方法能够在下面评论处推荐一下;