C语言文件操作详解:从打开到读写与结束判定
C语言中实现数据持久化主要依赖磁盘文件。本文系统讲解文件类型、文件指针FILE的结构意义,以及fopen/fclose的基础用法。深入解析顺序读写函数(字符、字符串、格式化及二进制流)与随机定位函数(fseek、ftell、rewind),并纠正feof在判断文件结束时的常见误区,提供完整的代码示例。
为什么使用文件
程序运行时的数据通常存储在内存中,断电或程序退出后数据即消失。为了实现数据的持久化,我们需要将数据存储到磁盘文件中或通过数据库保存。使用文件可以将数据直接存放在硬盘上,确保数据在关闭程序后依然存在,直到被显式删除。
什么是文件
在程序设计领域,“文件”的概念分为两类:
- 程序文件:包括源程序文件(后缀为
.c)、目标文件(Windows环境下后缀为.obj)和可执行程序(Windows环境下后缀为.exe)。 - 数据文件:文件的内容不一定是程序代码,而是程序运行时读写的数据,例如需要从中读取输入数据的文件,或者程序输出结果的文件。
每个文件必须有一个唯一的标识供用户识别,文件名由路径、文件主干名和后缀组成,例如:c:\cyuyan\test.txt。
文件指针
每一个被使用的文件在内存中都会开辟一个相应的文件信息区,用于存放文件的相关信息(如文件名、文件状态及当前读写位置等)。这些信息保存在一个名为 FILE 的结构体变量中。该结构体由系统声明,不同编译器的具体成员可能略有差异,但功能相似。
struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;为了操作文件,我们需要定义一个指向 FILE 类型的指针变量:
FILE* pf; // 文件指针变量
pf 指向某个文件的文件信息区,通过该指针即可访问关联的文件。
文件的打开和关闭
在使用文件前必须先打开它,打开时会返回一个 FILE* 指针,建立指针与文件的关系;使用完毕后必须关闭文件,以防止数据丢失或资源泄露。
第1步:打开文件
入口函数为 fopen,其原型如下:
FILE *fopen( const char *filename, const char *mode ); // filename - 要打开的文件名 // mode - 文件访问模式
常见的文件访问模式包括读、写、追加及其对应的文本/二进制变体。具体模式含义可参考下表:
第2步:使用与关闭文件
文件操作完成后,使用 fclose 关闭文件:
int fclose( FILE *stream );
以下是一个标准的文件打开、检查与关闭流程示例:
#include<stdio.h>
#include<errno.h>
int main()
{
// 1. 以写入模式打开文件
FILE* pf = fopen("data.txt", "w");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 0; // 注意:实际工程中应返回适当错误码
}
// 2. 在此处进行文件读写操作
// ...
// 3. 关闭文件并将指针置空
fclose(pf);
pf = NULL;
return 0;
}文件的顺序读写
顺序读写指按照文件内容的先后顺序依次读取或写入。根据数据类型和格式的不同,C语言提供了多组函数:
字符读写
fgetc(FILE *stream):从流中读取一个字符。fputc(int c, FILE *stream):将字符写入流。
字符串读写
fgets(char *string, int n, FILE *stream):从流中获取一个字符串,最多读取n-1个字符。fputs(const char *string, FILE *stream):将字符串写入流。
格式化读写
fscanf(FILE *stream, const char *format, ...):从流中读取格式化数据。fprintf(FILE *stream, const char *format, ...):将格式化数据写入流。
二进制读写
fread(void *buffer, size_t size, size_t count, FILE *stream):从文件中读取二进制数据块。fwrite(const void *buffer, size_t size, size_t count, FILE *stream):向流中写入二进制数据块。
需要注意的是,scanf/printf 仅针对标准输入/输出流 stdin/stdout,而 fscanf/fprintf 可以指定任意文件流。此外还有针对字符串的 sscanf/sprintf 用于内存中的格式化转换。
文件的随机读写
除了按顺序读写,C语言支持随机访问文件内部任意位置,主要通过以下三个函数实现:
第一步:定位文件指针 fseek
fseek 根据偏移量和起始位置移动文件指针:
int fseek( FILE *stream, long offset, int origin ); // stream - 文件指针 // offset - 起始字节数(偏移量) // origin - 起始位置(如 SEEK_SET, SEEK_CUR, SEEK_END)
第二步:获取当前位置 ftell
ftell 返回文件指针相对于起始位置的偏移量,可用于确定文件大小:
long ftell( FILE *stream );
第三步:重置指针 rewind
rewind 让文件指针回到文件的起始位置:
void rewind( FILE *stream );
文件结束判定
许多初学者误以为 feof 可以直接用来判断循环条件来读取文件,这是错误的。feof 应用于文件读取结束后,判断是导致结束的原因是“遇到文件尾”还是“读取失败”。
正确的判断方法应根据文件类型区别对待:
- 文本文件:判断返回值是否为结束标志。
- 使用
fgetc时,判断返回值是否为EOF。 - 使用
fgets时,判断返回值是否为NULL。
- 使用
- 二进制文件:判断实际读取的项目数是否小于预期数量。
- 使用
fread时,判断返回值是否小于count。
- 使用
文本文件读取结束的判断示例如图:
二进制文件读取结束的判断示例如图:
以上就是C语言文件操作的详细内容,更多关于C语言编程技巧的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









