C语言文件管理
操作文件的正常流程为打开文件–>读写文件–>关闭文件
-
打开文件,就是获取文件的有关信息,例如文件名、文件状态、当前读写位置等,这些信息会被保存到一个 FILE 类型的结构体变量中。
-
关闭文件就是断开与文件之间的联系,释放结构体变量,同时禁止再对该文件进行操作。
-
在C语言中,文件有多种读写方式,可以一个字符一个字符地读取,也可以读取一整行,还可以读取若干个字节。文件的读写位置也非常灵活,可以从文件开头读取,也可以从中间位置读取。
数据在文件和内存之间传递的过程叫数据流
打开文件
-
使用 <stdio.h> 头文件中的 fopen() 函数即可打开文件,它的用法为:
FILE *fopen(char *filename, char *mode);
filename为文件名(包括文件路径),mode为打开方式,它们都是字符串。
-
fopen()函数的返回值:fopen()会获取文件信息,包括文件名、文件状态、当前读写位置等,并将这些信息保存到FILE类型的结构体变量中,然后返回该变量的地址。
如果希望接收fopen()的返回值,就需要定义一个FILE类型的指针:FILE *fp=fopen("demo.txt","r");
表示以只读形式打开当前目录下的demo.txt文件,并使fp指向该文件,通过fp操作demo.txt,fp被称为文件指针。
-
文件打开方式有以下几种:
打开方式 | 说明 |
---|---|
“r” | “只读”,文件必须存在,否则打开无效 |
“w” | “写入”,如果文件存在,则清空文件内容(相当于删除原文件,再新建一个新文件);如果文件不存在,则创建一个新文件 |
“a” | “追加”,如果文件存在,则将写入的数据追加到文件末尾;如果文件不存在,则创建一个新文件 |
“r+” | “读写”,文件必须存在,随意更新文件 |
""w+ | “写入/更新”,相当于w和r+叠加的效果。既可以读取也可以写入,也就是随意更新文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么清空文件内容(相当于删除原文件,再创建一个新文件 |
“a+” | “追加/更新”,相当于a和r+叠加的效果。既可以读取也可以写入,也就是随意更新文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么将写入的数据追加到文件的末尾(文件原有的内容保留) |
“t” | 文本文件,如果不写,默认为"t" |
“b” | 二进制文件 |
关闭文件
文件使用完毕,应该使用fclose()函数把文件关闭,以释放相关资源,避免数据丢失,其用法为:
int fclose(FILE *fp);
正常关闭文件时,函数返回值为0。
对于Windows平台,最好使用"t"打开文本文件,用"b"打开二进制文件;对于Linux平台,使用"t"还是"b"都无所谓,既然默认是"t",什么都不写就可以了。
fgetc() 字符读取函数
用法为
int fgetc(FILE *fp);
读取成功时返回读取到的字符,读取失败或读取到文件末尾时返回EOF,EOF的值一般为-1。
文件读取失败或指向文件末尾时都返回EOF,那么如何判断文件读取完毕还是出错,可以借用stdio.h中的feof()和ferror()函数判断:
feof()函数用来判断文件内部指针是否指向了文件末尾:
int feof(FILE *fp);
当指向文件末尾时返回非零值,否则返回零值。
ferror()函数用来判断文件操作是否出错:
int ferror(FILE *fp);
当文件操作出错时返回非零值,否则返回零值。
示例:
#include<stdio.h>
int main() {
char ch;
FILE* fp;
//判断文件是否存在
if((fp = fopen("D:\\demo.txt", "rt")) == NULL){
puts("Fail to open file!");
exit(0);
}
//读取字符
while ((ch = fgetc(fp)) != EOF) {
putchar(ch);
}
putchar('\n');
//判断是否读取成功
if(ferror(fp)){
puts("读取出错");
}else{
puts("读取成功");
}
fclose(fp);
return 0;
}
fputc() 字符写入函数
fputc()函数的用法为:
int fputc(int ch,FILE *fp);
ch为要写入的字符,fputc()写入成功时返回写入的字符,失败时返回EOF.
示例:
#include<stdio.h>
int main() {
char ch;
FILE* fp;
//判断文件是否成功打开
if ((fp = fopen("D://demo.txt", "wt+")) == NULL) {
puts("Fail to open file!");
exit(0);
}
printf("Input a string:\n");
//每次从键盘读取一个字符并写入文件
while ((ch = getchar()) != '\n') {
fputc(ch, fp);
}
fclose(fp);
return 0;
}
fgets() 读取字符串函数
char *fgets(char *str,int n,FILE *fp);
此函数用来从指定的文件中读取一个字符串,并保存到字符数组str中,n为要读取的字符数目。
注意:
- 读取到的字符串会在末尾自动添加’\0’,所以实际只读取到了n-1个字符,如果需要读取100个字符,n的值应该改为101;
- 在读取到n-1个字符之前出现了换行,或者读取到文件末尾,则读取结束,fgets()只能读取一行数据,不能跨行;但是可以借助fgets(),将n的值设置的足够大,每次就可以读取到一行数据。
- 返回值:读取成功返回字符数组首地址,读取失败返回NULL。
fputs() 写入字符串函数
int fputs(char *str,FILE *fp);
此函数用来向指定的文件写入一个字符串str,写入成功返回非负数,失败返回EOF.
fread() 读取块数据
size_t fread(void *ptr,size_t size,size_t count,FILE *fp);
fwrite() 写入块数据
size_t fwrite(void *ptr,size_t size,size_t count,FILE *fp);
对参数的说明:
- ptr 为内存区块的指针,它可以是数组、变量、结构体等。fread() 中的 ptr 用来存放读取到的数据,fwrite() 中的 ptr 用来存放要写入的数据
- size:表示每个数据块的字节数
- count:表示要读写的数据块的块数
- fp:表示文件指针
返回值:
- 返回成功读写的块数,即count
fprintf() fscanf() 格式化读写文件
fscanf()和fprintf()与scanf()和printf()功能相似,区别在于fscanf()和fprintf()的读写对象不是键盘和显示器,而是磁盘文件。
int fscanf(FILE *fp,char *format,...);
int fprintf(FILE *fp,char *format,...);
仅仅多了一个fp参数,示例:
FILE *fp;
int i,j;
char *str,ch;
fscanf(fp,"%d %s",&i,str);
fprintf(fp,"%d %c",j,ch);
- fscanf()返回参数列表中被成功赋值的参数个数
- fprintf()返回成功写入的字符的个数,失败则返回负数。