配置文件读写案例实现分析
1、 功能划分
a) 界面测试(功能集成)
自己动手规划接口模型。
b) 配置文件读写
i. 配置文件读(根据key,读取valude)
ii. 配置文件写(输入key、valude)
iii. 配置文件修改(输入key、valude)
iv. 优化 ===》接口要求紧 模块要求松
2、 实现及代码讲解
3、 测试。
#include"cfg_op.h"
#define MAXLEN 1024
int GetCfgItem(char *pFilename, char* pKey, char *pValue, int *pValueLen)
{
FILE *fp = NULL;
int ret = 0;
char buf[MAXLEN] = { 0 };
char *pTmp = NULL;
fp = fopen(pFilename, "r");
if (fp == NULL)
{
ret = -1;
printf("打开文件失败。\n");
return ret;
}
while (!feof(fp))
{
memset(buf,0,sizeof(buf));
fgets(buf, MAXLEN, fp);//注意取出来的数据最后有一个/n结束符
//printf("%s\n",buf);
pTmp = strchr(buf,'=');
if (pTmp == NULL)//没有找到'='
continue;
pTmp = strstr(buf, pKey);
if (pTmp == NULL)//如判断pkey是不是在所在行
continue;
pTmp += strlen(pKey);// mykey1 = myvalue11111 => " = myvalue11111 "
pTmp = strchr(pTmp,'=');
if (pTmp == NULL)
continue;
pTmp = pTmp + 1; //=>" myvalue11111 "
//pTmp = " myvalue31111 ";
trimSpace(pTmp, pValue);
*pValueLen = strlen(pValue);
}
fclose(fp);
return 0;
}
int trimSpace(char *inbuf, char *outbuf)
{
int ret = 0;
char * p = inbuf;
int len = strlen(inbuf)-2;//减2的原因是最后有个'/n'结束符
int left = 0, right = len;
char *tmp = NULL;
if (!inbuf)
{
ret = -1;
printf("inbuf is NULL. \n");
return -1;
}
while (p[right] == ' ')
right--;
while (p[left] == ' ')
left++;
if (left >= right)
{
outbuf = NULL;
return ret;
}
memset(outbuf, 0, strlen(outbuf));
strncpy(outbuf, p + left, right - left+1);
return ret;
}
//写配置项
//循环读每一行,检查key是否存在,若存在修改对应的value,若不存在在文件尾添加“key=value
/*本实现方法是将文件内容一行一行取出存入临时数组,修改目标行也存入临时数组,再将后面的再润如临时数组,
之后再重新创建同名文件,将数组内容写入文件*/
/该方法的实现有个缺陷就是如果文件比较大,临时数组就要申请较大内存/
/*新方法:将数据从文件filea取出存入新的文件fileb,然后将filea删除(remove),再将fileb改名成filea(rename),
这种方法的实现避免的较大文件需要申请较大内存的问题,但因为是和硬盘交互,速度上较慢*/
int WriteCfgItem(char *pFilename, char* pkey, char *pvalue, int ValueLen)
{
int rv = 0;
FILE *fp;
long len = 0;
char linebuf[100] = {0};
char filebuf[8 * 1024] = { 0 };
char *ptmp;
int itag = 0;
if (pFilename == NULL || pkey == NULL || pvalue == NULL)
{
rv = -1;
printf("parameter error.\n");
goto EXIT;
}
fp = fopen(pFilename,"r+");
if (fp == NULL)
{
fp == fopen(pFilename,"w+t");
if (fp == NULL)
{
rv = -2;
printf("fopen error.\n");
goto EXIT;
}
}
fseek(fp, 0L, SEEK_END);//把文件指针从0开始,移到文件末尾。
len = ftell(fp);//获取文件长度
if (len > 1024 * 8)
{
rv = -3;
printf("超过8k,不支持。\n");
goto EXIT;
}
while (!feof(fp))
{
//读每一行
memset(linebuf, 0, sizeof(linebuf));
ptmp = fgets(linebuf, 1024, fp);
if (ptmp == NULL)
break;
ptmp = strstr(linebuf, pkey);
if (ptmp == NULL)//关键字不在本行
{
strcat(filebuf, linebuf);
continue;
}
else//关键字在本行
{
sprintf(linebuf, "%s=%s\n", pkey, pvalue);
strcat(filebuf, linebuf);
itag = 1;
}
}
if (itag == 0)//若关键字不存在,追加
{
fprintf(fp, "%s = %s\n", pkey, pvalue);
}
else//若关键字存在,则重新写文件内容
{
if (fp != NULL)
{
fclose(fp);
fp = NULL;
}
fp = fopen(pFilename, "w+t");
if (fp == NULL)
{
rv = -4;
printf("fopen error.\n");
goto EXIT;
}
fputs(filebuf, fp);
}
EXIT:
if (fp != NULL)
fclose(fp);
return rv;
}
=========测试框架===========
#include<stdlib.h>
#include"cfg_op.h"
#define CFIGNAME "C:/mycfg.ini"
void mymenu()
{
printf("===========================\n");
printf("1 测试写配置文件。\n");
printf("2 测试读配置文件。\n");
printf("0 退出。\n");
printf("===========================\n");
}
int TWriteCfg()
{
char pItemName[100] = {0};
char pItemValue[100] = {0};
int itemValueLen = 0;
int ret = 0;
printf("\n请输入key:");
scanf("%s", &pItemName);
printf("\n请输入Value:");
scanf("%s", &pItemValue);
itemValueLen = strlen(pItemValue);
ret = WriteCfgItem(CFIGNAME, pItemName, pItemValue, itemValueLen);
if (ret != 0)
{
printf("WriteCfgItem error \n");
return ret;
}
printf("输入:%s = %s", pItemName, pItemValue);
return 0;
}
int TGetCfg()
{
char pKey[20] = {0};
char pValue[100] = { 0 };
int pValueLen = 0;
int ret = 0;
printf("\n请输入key:");
scanf("%s", &pKey);
pValueLen = strlen(pValue);
ret = GetCfgItem(CFIGNAME,pKey, pValue, &pValueLen);
if (ret != 0)
{
printf("GetCfgItem error \n");
return ret;
}
printf("pValue=%s\n", pValue);
printf("pValueLen=%d\n", pValueLen);
return 0;
}
int main()
{
int choice;
for (;;)
{
mymenu();
scanf("%d", &choice);
switch (choice)
{
case 1://写配置项
TWriteCfg();
break;
case 2://读
TGetCfg();
break;
case 0:
exit(1);
default:
break;
}
}
return 0;
}