#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
/**************************************************************************
* getKeyPos()内部调用,用来在获取key值之前,
* 筛出key之前的空格
**************************************************************************/
static int isSpaceBehindKey(FILE *fp,int pos){
char m=0;
char cb=0;
int newPos=0;
fseek(fp,pos,SEEK_SET);
fread(&cb,1,1,fp);
while(cb == ' '){
m++;
fread(&cb,1,1,fp);
}
(m>0)?(newPos=ftell(fp)-1):(newPos=pos);
fseek(fp,newPos,SEEK_SET);
return 0;
}
/************************************************************************
* getKey() 、setKey()都调用此函数获取要操作的属性所在位置
************************************************************************/
static int getKeyPos(FILE *fp,char *p){
char *line = NULL,*token=NULL;
char pEdit[100]={'\0'},lineEdit[100]={'\0'};
size_t len = 0;
strcpy(pEdit,p);
strcat(pEdit,"=");
int pos=0,jum=0;
int ret=isSpaceBehindKey(fp,pos);
if(ret<0){
printf("isSpaceBehindKey err\n");
return -1;
}
while ((getdelim(&line, &len,'=', fp)) != -1) {//获取‘=’之前的字符串,包括‘=’
strncpy(lineEdit,line,strlen(p));
strcat(lineEdit,"=");
if((strcmp(pEdit,lineEdit))==0){
ret = pos;
jum=1;
break;
}
getline(&line, &len, fp);
pos=ftell(fp);
int ret=isSpaceBehindKey(fp,pos);
if(ret<0){
printf("isSpaceBehindKey err\n");
ret = -1;
}
memset(lineEdit,0,strlen(lineEdit));
}
if(!jum)ret=-1;//如果没找到,返回-1.
free(line);
return ret;
}
/***********************************************************************
* 上层直接调用,获取指定key的属性值,获取到的内容回填到getBuff地址
***************************************************************************/
int getKey(FILE *fp,char *p,char* getBuff){
char Buff[100]={'\0'};
char *line = NULL;
int i=0;
size_t len = 0;
int keypos = getKeyPos(fp,p);
if(keypos<0){
printf("getKeyPos err:%s\n",strerror(errno));
return -1;
}
getline(&line, &len, fp);
//截取换行符之前的字符串
strcpy(Buff,strtok(line,"\n"));
while(Buff[i]==' '){
i++;
}
strcpy(getBuff,&Buff[i]);
free(line);
return 0;
}
/*************************************************************
* setKey()内部调用,用来获取删除欲修改行之后的文件大小,
* 之后可以调用truncate()改变文件大小到新的大小
****************************************************************/
static int getfilesize(FILE* fp,int keypos){
size_t len=0;
char *line=NULL;
int filesize=0,pos=0;
pos=(int)ftell(fp);
//printf("keypos:%d\n",keypos);
fseek(fp,keypos,SEEK_SET);
if(-1 == (getline(&line, &len, fp))){
printf("getline err:\n");
return -1;
}
fseek(fp,0,SEEK_END);
printf("file:%d len:%d\n",(int)ftell(fp),(int)strlen(line));
filesize = (ftell(fp))-(strlen(line));
fseek(fp,pos,SEEK_SET);
free(line);
return filesize;
}
/***************************************************************
* setKey()内部调用,用来改变最终文件大小,并将欲修改之属性
* 写到文件尾
****************************************************************/
static int trunfile(int filesize,char *p,char* setBuff,FILE *fp,int flag){
char Buff[100]={'\0'};
truncate("/data/mrzhang/testfile",filesize);
memcpy(Buff,p,strlen(p));
strcat(Buff,"=");
strcat(Buff,setBuff);
(0==flag)?(fprintf(fp,"\n%s",Buff)):(fprintf(fp,"%s",Buff));
return 0;
}
/***********************************************************
* 上层直接调用,设置属性
************************************************************/
int setKey(FILE *fp,char *p,char* setBuff){
size_t len = 0;
char *line = NULL;
char cb=0,Buff[100]={'\0'};
int newpos=0,ret=0,filesize=0,flag=0,markkeypos=0;
int keypos = getKeyPos(fp,p);
if(keypos<0){//添加新属性
memcpy(Buff,p,strlen(p));
strcat(Buff,"=");
strcat(Buff,setBuff);
fprintf(fp,"\n%s",Buff);
goto err;
}
getline(&line, &len, fp);//通过getline()操作,将文件指针移动到要设置的key所在行的下一行起始处
filesize = getfilesize(fp,keypos);
if(filesize<0){
ret = -1;
goto err;
}
markkeypos = keypos;
while(-1 != (getline(&line, &len, fp))){//读取一行到line
newpos = ftell(fp);//记录下次要读取的位置
fseek(fp,keypos,SEEK_SET);//指定重置到上次记录的写位置
fprintf(fp, "%s", line); //将line内容写文件
keypos = ftell(fp);//记录下次要写的位置
if(keypos >= filesize){//如果下次要写的位置值大于等于删除欲修改行之后文件的大小,循环将结束
break;
}
fseek(fp,newpos,SEEK_SET);
}
if(markkeypos>=filesize){
fseek(fp,keypos,SEEK_SET);
flag=1;
}
trunfile(filesize,p,setBuff,fp,flag);//退出循环前将要设置的属性写在文件尾
err:
free(line);
return ret;
}
/*int main(){
FILE *fp;
char *p="Q";
char setBuff[20]="A B";
char getBuff[20] = {0};
fp = fopen("/data/mrzhang/testfile", "r+");
if (fp == NULL)
exit(EXIT_FAILURE);
//setKey(fp,p,setBuff);
printf("----------%d\n",setKey(fp,p,setBuff));
printf("----------=%d\n",getKey(fp,p,getBuff));
printf("%s=%s\n",p,getBuff);
fclose(fp);
}*/