文件
本文将详述C语言中关于文件的相关知识。
文件是数据源的一种,主要的作用是保存数据。
在操作系统中,为了统一对各种硬件的操作,简化接口,不同的硬件设备也都被看成一个文件。对这些文件的操作,等同于对磁盘上普通文件的操作。列如:
●通常把显示器称为标准输出文件,printf就是向这个文件输出数据。
●通常把键盘称为标准输入文件,scanf就是从这个文件读取数据。
常见输出设备对应的文件:
文件 | 硬件设备 |
---|---|
stdin | 标准输入文件,一般指键盘: scanf() getchar()… |
stdout | 标准输入文件,一般指显示器 print() putchar()等 |
stderr | 标准错误文件,一般指显示器;perror()等 |
stdprn | 标准打印文件,一般指打印机 |
C语言把文件分为ASCII文件和二进制文件。ASCII文件又称文本文件。
文件流:指数据在文件和内存之间传递的过程。
输入流:指数据从文件复制到内存的过程。
输出流:从内存保存到文件的过程。
数据流(Data Stream):指数据在数据源和程序(内存)之间传递的过程。
输入流(Input Stream):数据从数据源到(内存)程序的过程。
输出流(Output Stream):数据从程序(内存)到数据源的过程。
文件输入输出方式也称”存取方式”。C语言中,文件有两种存取方式:顺序存取和直接存取。
文件类型指针
可以用结构体类型来定义文件类型的指针变量,一般形式为:
FILE *fp;
fp是一个指向FILE结构体类型的指针变量。
文件的打开与关闭
打开文件
1.调用形式:
FILE *fp = fopen(文件名,文件使用方式);
●函数返回一个指向FILE类型的指针。
●无论哪种使用方式,当打开文件时出现错误,fopen函数都将返回NULL。
2.常用文件打开方式及说明:
【控制读写权限(必须指明)】
打开方式 | 说明 |
---|---|
r | 以”只读”方式打开文件。只允许读取,不允许写入。文件必须存在,否则打开失败。 |
w | 以”写入”方式打开文件。如果文件不存在,那么创建一个新文件,如果文件存在,那么清空文件内容(相当于删除源文件,再创建一个新文件。) |
a | 以”追加”方式打开文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么将写入的数据追加到文件末尾(文件原有的内容保留) |
r+ | 以读写方式打开文件。既可以读取也可以写入,也就是随意更新文件。文件必须存在,否则打开失败。 |
w+ | 以”写入/更新”方式打开文件,相当于w和r+叠加的效果。首先建立一个新文件,进行写操作,随后可以从头开始读。如果指定文件已存在,则原有内容会被清空。 |
a+ | 以”追加/更新”方式打开文件,相当于a和r+叠加的效果。既可以读也可写,也就是随意更新文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么将写入的数据追加到文件末尾。 |
【控制读写方式(可省略)】
打开方式 | 说明 |
---|---|
“t” | 文本文件。如果不写,默认为”t”。 |
“b” | 二进制文件 |
●调用fopen()函数时必须指明读写权限,但是可以不指明读写方式(此时默认为”t”)
●读写权限和读写方式可以组合使用,但必须以读写权限开头。
●整体来说,文件打开方式由r、w、a、t、b、+等6个字符拼成,各字符含义如下:
r(read) | w(write) | a(append) | t(text) | b(banary) | + |
---|---|---|---|---|---|
读 | 写 | 追加 | 文本文件 | 二进制文件 | 读和写 |
关闭文件
文件一旦使用完毕,应该用fclose()函数把文件关闭,以释放相关资源,避免数据丢失。
1.fclose()的用法为:
int fclose(FILE *fp);
fp为文件指针,如 fclose(fp);
2.使用说明:
●若对文件的操作方式为”读”方式,则经以上函数调用之后,要使文件指针与文件脱离联系。可以重新分配文件指针去指向其他文件。
●若对文件的操作方式为”写”方式,则系统首先把该文件缓冲区中的剩余数据全部输出到文件中,然后使文件指针与文件脱离联系。
●在完成了对文件的操作后,应当关闭文件,否则文件缓冲区中剩余数据就会丢失。
●当执行了关闭操作后,成功则函数返回0,否则返回非0。
文件的读写
以字符形式读写文件
以字符形式读写文件时,每次可以从文件读取一个字符,或者向文件中写入一个字符。主要使用两个函数,分别是fgetc()和fputc()。
◆字符读取函数fgetc():
fgetc是 file get char的缩写,意为从指定文件中读取一个字符。
一般形式: int fgetc(FILE *fp);
fp为文件指针;fgetc()读取成功时返回读取到的字符,读取到文件末尾或读取失败时返回EOF.
EOF(End of File)表示文件末尾,是在stdio.h中定义的宏,它的值往往为-1是负数。
在读取文件时,文件内部由系统设置一个位置指针,用于指向当前读写的位置;在文件打开时总是指向文件中的第一个字节,每次fgetc()使用后该位置指针会向后移动一个字节,所以可以连续使用fgetc()读取多个字符。
【程序示例】在屏幕上显示D:\\demo.txt
文件的内容。
1 |
|
对EOF的说明:EOF本意指文件末尾,但读取文件出错时也会返回EOF。
要进一步判断读取状态可借助stdio.h中的feof()和ferror()函数。
feof()函数:用于判断文件内部指针是否指向末尾,当指向文件末尾时返回非零值,否则返回为0。
一般形式:
int feof(FILE *fp);
ferror()函数:用于判断文件操作是否出错,当文件操作出错时返回非零值,否则返回为0。
一般形式:
int ferror(FILE *fp);
◆字符写入函数fputc():
fputc 是file output char 的缩写,意为向指定文件写入一个字符。
一般形式:
int fputc(int ch,FILE *fp);
ch为要写入的字符,fp为文件指针。fputc()写入成功时返回写入的字符,失败时返回EOF,返回值类型为int即可容纳这个值(负数)。
语句示列:把字符’a’写入fp所指向的文件中
fputc(‘a’,fp); 或 char ch=’a’; fputc(ch,fp);
【程序示例】从键盘输入一行字符,写入文件。
1 |
|
fgetc()和fputc()函数每次只能读写一个字符,速度较慢;实际开发中往往读写字符串或数据块。
以字符串形式读写文件
◆读取字符串函数fgets():
fgets()函数用来指定文件中读取一个字符串,并保存到字符数组中。
一般形式:
char *fgets(char *str,int n,FILE *fp);
str为字符数组,n为要读取的字符数目,fp为文件指针。
返回值:读取成功时返回字符数组首地址,也即str;读取失败时返回NULL;如果开始读取文件内部指针已指向了末尾,那么读取不到任何文字,也返回NULL。
▲注意:读取到的字符串会在末尾自动添加’\0’,n个字符有n+1个长度,遇到换行符会一并读取到字符串。
【程序示例】一行一行地读取文件
1 |
|
◆写字符串函数fputs():
fputs()函数用来向指定的文件写入一个字符串。
一般形式为:
int fputs(char *str,FILe *fp);
str为要写入的字符串,fp为文件指针。写入成功则返回非负数,否则返回EOF。
【程序示例】向d:\\demo.txt
文件中追加一个字符串
1 |
|
以数据块的形式读写文件
如果需要读取多行内容,需要使用fread()函数;相应地写入函数为fwrite()。
数据块:即若干个字节的数据,可以是一个字符、一个字符串或多行数据,并没有什么限制。
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表示文件指针
●理论上每次读写 sizecount个字节的数据
●size_t是typedef定义的无符号整型数据类型,表示数量。
●返回值:返回成功读写的块数,也即count。
若返回值小于count:
fwrite() | fread() |
---|---|
肯定发生了写入错误,可用ferror()函数检测 | 可能读到了文件末尾,可能发生了错误,可用ferror()、feof()检测 |
rewind(fp):将文件中的指针重新定位到文件开头。
【程序示例】从键盘输入两个学生数据,写入一个文件中,再次读出这两个学生数据到屏幕上。
1 |
|
格式化读写文件
以磁盘文件作为读写对象的格式化读写函数fscanf()和fprintf()。
一般形式:
int fscanf(FILE *fp,char *format,…);
int fprintf(FILE *fp,char *format,…);
fp为文件指针,format为格式控制字符串,…表示参数列表。
返回值:
fprintf()返回成功写入字符的个数,失败则返回负数。
fscanf()返回参数列表中被成功赋值的参数个数。
随机读写文件
所谓随机读写指移动文件内部的位置指针后再进行读写。经常用于实际开发中读取文件的中间部分。
实现随机读写的关键是按要求移动位置指针,这称为文件的定位。
rewind()函数用于将位置指针移动到文件开头,原型为:
void rewind(FILE *fp);
fseek()函数用于将位置指针移动到任意位置,它的原型为:
int fseek(FILE *fp,long offset,int origin);
说明:
●fp为文件指针
●offset为偏移量,也就是要移动的字节数。offset为正,向后移动;为负,向前移动。
●origin为起始位置,也就是从何处开始计算偏移量。C语言的起始位置有以下三种,如下:
起始位置 | 常量名 | 常量值 |
---|---|---|
文件开头 | SEEK_SET | 0 |
当前位置 | SEEK_CUR | 1 |
文件末尾 | SEEK_END | 2 |
●fseek一般用于二进制文件。
版权声明
Scholar’s Blog by scholargeek is licensed under a Creative Commons BY-NC-ND 4.0 International License.
由董仕麟创作并维护的scholargeek博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证。
本文首发于Scholar’s Blog博客,版权所有,侵权必究。
本文永久链接:https://scholargeek.github.io/2018/02/20/C%E8%AF%AD%E8%A8%80%E5%AD%A6%E4%B9%A010/