c语言:文件处理操作-1
https://developer.aliyun.com/article/1515718
四、顺序读写
我们已经知到该如何打开和关闭我们要访问的文件,但是,如何对文件内部用代码进行操作呢?
接下来就要谈到顺序读写函数
顺序读写函数
功能 | 函数名 | 用于 |
字符输入函数 | fgetc | 所有输入流 |
字符输出函数 | fputc | 所有输出流 |
文本行输入函数 | fgets | 所有输入流 |
文本行输出函数 | fputs | 所有输出流 |
格式化输入函数 | fscanf | 所有输入流 |
格式化输出函数 | fprintf | 所有输出流 |
二进制输入 | fread | 文件 |
二进制输出 | fwrite | 文件 |
1、fputc
作用:将字符写入文件
返回值为字符ascll码值,类型为int,int character 为字符的ascll码值,stream为文件流
- 返回值为所写入字符的ascll码值。
- 每次写入都会让位置指示器所指向的字符将向后移一位。
- 如果写入错误,将会返回EOF,并为文件指示器设置ferror。
例如,我们要对一个文本文件进行写入26个小写字母的操作:
#include<stdio.h> #include<stdlib.h> int main() { int a = 0; FILE* pf = fopen("ilike.txt", "w"); //打开文件 if (pf == NULL) printf("pf fopen \"ilike\" fail"); else { for (int i = 0;i < 26;i++) { a=fputc('a'+i, pf);//文件写入操作 printf("%d ", a); } fclose(pf);//关闭文件 pf = NULL;//将pf滞空,防止野指针 } system("pause"); return 0; }
打开项目目录查看ilike.txt的文件查看,结果如下:
2、fgetc
既然能将字符写入文件,那么自然也能从文件读取字符进行输出。我们查阅c++reference可以看到
解释说明:
- int fgetc (FILE * stream); 返回值为访问的文件的当前位置指示符指向的字符的ascll码值,参数为文件流。
- 每次读取后,当前位置指示符指向的字符会指向下一个字符。
- 如果在调用的时候遇到文件尾,则返回EOF(值为-1).
- 如果读取错误,则返回EOF并为流设置错误指示符FERROR。
读的时候,打开方式用"r",我们读取上面用fputc写入的26个小写字母并打印出来,举个例子:
#include<stdio.h> #include<stdlib.h> int main() { int arr[26] = { 0 }; FILE* pf = fopen("ilike.txt", "r"); if (pf == NULL) printf("pf fopen \"ilike\" fail"); else { for (int i = 0;i < 26;i++) { arr[i] = fgetc(pf); } fclose(pf); pf = NULL; } for (int i = 0;i < 26;i++) { printf("%c ", arr[i]); } system("pause"); return 0; }
运行结果如图
如果对文件的操作每次只能读取或者写入一个字符,那么效率会不会有点低下了?
这就要说说下面两个函数了:fgets,fputs。
3、fputs
首先想要使用这个函数,就必然要看看这个函数是如何定义的,同样我们查阅c++reference:
解释一下:
- 作用:将一个字符串写入文件流。(str是要写入的字符串,stream为文件流)
- 如果写入成功,则返回一个非负的值,如果写入失败则返回EOF,并未该文件设置错误的指示器。
#include<stdio.h> #include<stdlib.h> int main() { char arr[10] = { 0 }; //定义要写入的字符串 int a = 0; for (int i = 0;i < 9;i++) { arr[i] = 'x'; } FILE* pf = fopen("ilike.txt", "w"); //打开文件 if (pf == NULL) printf("pf fopen \"ilike\" fail"); else { a=fputs(arr, pf); //写入文件 fclose(pf); // 关闭文件 pf = NULL; //指针置空 } printf("%d", a); system("pause"); return 0; }
打开工程目录里面的ilike.txt文件,结果如下
(我们用一个整形接收fputs的返回值,结果为0)
注意: 如果使用两个 fputs(),对一个文件分别写入两个字符串,如果第一个写入的字符串末尾没有'\n',那么两个字符串将会在同一行进行写入。
4、fgets
既然能一行一行地写入,那么必然能一行一行地读取:查阅c++reference,结果如下
这里不再进行过多地截取,可以自行查阅
cplusplus网站:
cplusplus.com - The C++ Resources Network
- 返回值为读取到地字符串的地址,类型为char*
- 读一个字符串,然后将字符串存入str所指向的数组,直到遇到换行符或者文件末尾
- 使用int num来控制读取字符串的长度。
- fgets读取遇到换行符停止读取,但是函数认为他是有效字符,并将其一起复制到str指向的字符串。
- 在读取完字符后,str后面会自动追加终止字符。
- 如果读取错误,则返回值为一个空指针,成功则返回的是str。
直接上代码:
#include<stdio.h> #include<stdlib.h> int main() { char arr[100] = { 0 }; FILE* pf = fopen("ilike.txt", "r"); if (pf == NULL) printf("pf fopen \"ilike\" fail"); else { fgets(arr,23,pf); fclose(pf); pf = NULL; } printf("%s", arr); system("pause"); return 0; }
这里,文件里面原来的数据为a-z,26个小写字母。我们使用fgets(arr,23,pf)来读取前23位
并打印arr,结果如下:后三位如预测结果一样未打印。
注意:这里不管是每行还是单个字符读取,每次操作完,位置指示器都会指向下一个将被读取的目标。
例如读取 文本文件中存在这样一串数据 : abcdefgh
使用fgets 读取前五个字符,原本位置指示器指向a,在读取五个字符后,位置指示器指向f所在的位置
对于文件的操作如果只是单个字符或者单个字符串的进行读取和写入,那么对文件的操作的精准度就不会很高,所以定义格式化输入输出函数来对文件进行操作:
5、fprintf
将文件格式化输出,其定义如下
stream为要写入的文件流,后面紧跟要输入数据的格式和对应的数据。
直接上代码:我们格式化写入一个结构体类型的数据。
- 如果写入成功,则返回写入字符的总数
- 如果写入错误,则设置指示符FERROR并返回一个负数
#include<stdio.h> #include<stdlib.h> struct S { char name[20]; int age; }; int main() { S s = { "xiaoxin",18 }; FILE* pf = fopen("ilike.txt", "w"); if (pf == NULL) printf("pf fopen \"ilike\" fail"); else { fprintf(pf,"%s %d",s.name,s.age); fclose(pf); pf = NULL; } system("pause"); return 0; }
对应目录里ilike.txt文件的内容被修改为:
我们可以将其和printf做一个对比
发现唯一不同的就是在前面的参数,fprintf多了一个FILE*类型的指针变量,这个变量就是用来定位你所要写入的文件。
6、fscanf
同样的,我们首先将其和scanf做一个对比:
同样是多了一个指向文件的FILE*类型的指针。
- 写入成功,函数返回参数列表中成功写入的项数
- 如果读取发生错误或者读到了文件末尾,则设置正确的指示符feof,
- 如果在成功读取任何数据之前,都会返回EOF
我们将之前的写入的结构体变量进行写入操作,并将读取到的数据赋值给另外一个同名结构体不同变量a,并打印。
#include<stdio.h> #include<stdlib.h> struct S { char name[20]; int age; }; int main() { S a = { "xiaoxin",18 }; FILE* pf = fopen("ilike.txt", "r"); if (pf == NULL) printf("pf fopen \"ilike\" fail"); else { fscanf(pf,"%s %d",&a.name,&a.age); fclose(pf); pf = NULL; } printf("%s %d", a.name, a.age); system("pause"); return 0; }
结果如下:
c语言:文件处理操作-3