C语言 文件操作10--配置文件读写
//配置文件读写项目 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<string.h> int writefile(const char *path/*in*/, char *pkey/*in*/, char *pvalue/*in*/){ int ERRO_MSG = 0; if (path == NULL) { ERRO_MSG = 1; printf("path==NULL erro msg:%d\n", ERRO_MSG); return ERRO_MSG; } if (pkey == NULL) { ERRO_MSG = 2; printf("pkey==NULL erro msg:%d\n", ERRO_MSG); return ERRO_MSG; } if (pvalue == NULL) { ERRO_MSG = 3; printf("pvalue==NULL erro msg:%d\n", ERRO_MSG); return ERRO_MSG; } //定义文件读指针 FILE *fpwr = fopen(path, "r+"); //判断文件是否打开成功 if (fpwr == NULL) { ERRO_MSG = 4; printf("文件打开失败!erro msg:%d;文件路径是%s\n", ERRO_MSG, path); return ERRO_MSG; } //判断原来配置文件里是否有该节点,有该配置节点执行修改操作,没有执行新增操作 //准备字符指针数组,存储所有的键值对 //定义下标 int index = 0; char **bufarr = (char **)malloc(sizeof(char *)*(index + 1)); //存储所有的配置文件(这里读取键值对,用fgets()函数比较合适,因为一行正好一个键值对) while (!feof(fpwr)){//feof()如果文件结束,则返回非0值,否则返回0 //定义文件缓存数组 char buf[100] = { 0 }; //读取文件 fgets(buf, 100, fpwr); //分配每个键值对内存存储空间 char *ptemp = (char *)malloc(sizeof(char)*((int)strlen(buf) + 1)); //拷贝字符串(buf定义在栈里,出了该函数会自动释放) strcpy(ptemp, buf);//strcpy()把从src地址开始且含有'\0'结束符的字符串复制到以dest开始的地址空间。 //把字符串挂到指针数组上 bufarr[index++] = ptemp; //为指针数组再次分配内存空间 bufarr = (char **)realloc(bufarr, sizeof(char *)*(index + 1)); } //为指针数组最后一个元素赋值NULL bufarr[index] = NULL; //开始查找对应键值对 int a = 0; char *strindex = NULL; while (bufarr[a] != NULL){ char *ptsource = bufarr[a]; while (*ptsource != '\0'){ int b = 0, flag = 0; //strchr函数原型:extern char *strchr(const char *s, char c); 返回首次出现c的位置的指针,返回的地址是被查找字符串指针开始的第一个与Val相同字符的指针,如果s中不存在c则返回NULL。 char *ptempc = strchr(ptsource, pkey[b]); ptsource = strindex = ptempc; if (ptempc == NULL) { //没有找到该字符串 flag = 1; break; } //开始匹配字符串 while (pkey[b] != '\0'){ //一个一个字符进行比较 if (*(ptempc++) != pkey[b++]) { flag = 1; strindex = NULL; break; } } break; } if (strindex != NULL) { //执行修改操作 //释放原来的字符串 if (bufarr[a] != NULL) { free(bufarr[a]); char newbuf[100] = { 0 }; sprintf(newbuf, "%s=%s\r\n", pkey, pvalue); //开辟新的字符串内存空间 char *pnewstr = (char *)malloc(sizeof(char)*((int)strlen(newbuf) + 1)); //复制字符串 strcpy(pnewstr, newbuf); bufarr[a] = pnewstr; } break; } a++; } //没有找到对应的键 if (strindex == NULL) { //执行新增操作 bufarr = (char **)realloc(bufarr, sizeof(char *)*(index + 2)); char newbuf[100] = { 0 }; sprintf(newbuf, "%s=%s\r\n", pkey, pvalue); //开辟新的字符串内存空间 char *pnewstr = (char *)malloc(sizeof(char)*((int)strlen(newbuf) + 1)); //拷贝字符串 strcpy(pnewstr, newbuf); bufarr[index] = pnewstr; bufarr[index + 1] = NULL; } int index2 = 0; //关闭文件指针 if (fpwr != NULL) { fclose(fpwr); } //为什么这里我会重新打开文件呢 //因为fopen()操作了文件指针fpwr,现在文件指针指向了文件末尾,(文件指针不同文件内部的位置指针,即fpwr(文件指针),(文件位置指针)fpwr->_ptr) //如果不关闭文件指针fpwr,那么写文件就会从文件末尾开始写,导致数据的追加 //但是也有别的办法 //就是使用rewind(fpwr)方法 //函数名: rewind() //功 能 : 将文件内部的位置指针重新指向一个流(数据流 / 文件)的开头 //注意:不是文件指针而是文件内部的位置指针,随着对文件的读写文件的位置指针(指向当前读写字节)向后移动。而文件指针是指向整个文件,如果不重新赋值文件指针不会改变。 //打开新文件指针 FILE *pfw = fopen(path, "w"); //fflush(fpwr); //开始写文件 while (bufarr[index2] != NULL){ //将文件写入到缓存 fputs(bufarr[index2], pfw); //释放字符指针数组元素内存 free(bufarr[index2]); index2++; } //释放字符指针数组内存 free(bufarr); //关闭文件指针 if (pfw != NULL) { fclose(pfw); } return ERRO_MSG; } int readfile(const char *path/*in*/){ int ERRO_MSG = 0; if (path == NULL) { ERRO_MSG = 1; printf("path!=NULL erro msg:%d\n", ERRO_MSG); return ERRO_MSG; } //定义文件指针 FILE *fpr = NULL; //打开文件 fpr = fopen(path, "r"); if (fpr == NULL) { ERRO_MSG = 2; printf("文件打开失败 erro msg:%d\n", ERRO_MSG); return ERRO_MSG; } while (!feof(fpr)){ char buf[100] = { 0 }; fgets(buf, 100, fpr); printf("%s", buf); } //关闭文件指针 if (fpr != NULL) { fclose(fpr); } return ERRO_MSG; } void testf1(const char *path/*in*/){ char buf1[100] = { 0 }; char buf2[100] = { 0 }; printf("请输入键:\n"); scanf("%s", buf1); printf("请输入值:\n"); scanf("%s", buf2); writefile(path, buf1, buf2); } void main(){ char *path = "E:/Test/CwordTest/b1.txt"; while (1){ int num = 0; printf("请输入对应的操作:\n"); printf("添加新的键值对请按1:\n"); printf("查询所有键值对请按2:\n"); printf("修改键值对请按3:\n"); scanf("%d", &num); switch (num) { case 1: testf1(path); break; case 2: readfile(path); break; case 3: testf1(path); break; default: break; } } system("pause"); }