第九章 文件
第二节 文件的读写操作
概述
在C语言程序设计中,文件操作是实现数据持久化存储的重要手段。本节重点讲解文件的读写操作,包括文件的打开、关闭、读写函数的使用及其相关原理,帮助考生系统理解并掌握文件操作的基本技能。通过本节学习,考生能够熟练地完成文本文件和二进制文件的数据读写,解决实际编程中的文件处理问题,为全国计算机等级考试二级C语言程序设计科目打下坚实基础。
核心概念
- 文件(File):存储在外部存储设备上的数据集合,可以是文本文件或二进制文件。
- **文件指针(FILE *)**:C语言中用于操作文件的指针类型,指向文件结构体,包含文件状态信息。
- 打开文件(fopen):为文件分配文件指针并打开文件,指定读写模式。
- 关闭文件(fclose):关闭文件,释放系统资源。
- 文本文件与二进制文件:文本文件以字符形式存储数据,二进制文件以字节形式存储。
- 读写函数:标准库提供的函数,如fgetc、fgets、fputc、fputs、fread、fwrite等,用于文件内容的操作。
原理分析
C语言的文件操作是基于缓冲区和文件指针机制实现的。文件指针不仅记录文件的打开状态,还维护当前读写位置。文件的读写操作通过标准库函数调用完成,系统通过缓冲机制提高读写效率。文件的打开模式决定了文件的访问权限及读写方式。
文件的读写分为文本读写和二进制读写:
- 文本读写通过字符或字符串函数处理,对换行符等特殊字符进行转换。
- 二进制读写通过块状数据读写函数处理,数据不做转换,适合处理非文本数据。
操作流程一般为:打开文件->读写数据->关闭文件。过程中应注意文件是否成功打开,以及操作的返回值,防止程序异常。
详细内容
1. 文件的打开与关闭
打开文件是进行文件读写的第一步,使用函数原型:
FILE *fopen(const char *filename, const char *mode);
- filename:文件名,支持相对路径和绝对路径。
- mode:文件打开模式,常用模式包括:
- "r":只读,文件必须存在
- "w":只写,若文件存在则清空,不存在则创建
- "a":追加写,文件不存在则创建
- "rb", "wb", "ab":二进制模式下的读、写、追加
打开成功返回文件指针,失败返回NULL。
关闭文件使用:
int fclose(FILE *stream);
关闭后文件指针无效,释放系统资源。
2. 文本文件的读写操作
文本文件以字符为单位进行读写,常用函数有:
- 读取字符:
int fgetc(FILE *stream);读取一个字符,返回字符的ASCII码,遇到文件末尾返回EOF。 - 写入字符:
int fputc(int char, FILE *stream);写入一个字符。 - 读取字符串:
char *fgets(char *str, int n, FILE *stream);读取一行或指定长度字符串,遇换行符或n-1字符停止。 - 写入字符串:
int fputs(const char *str, FILE *stream);写入字符串,不自动添加换行。
注意:
- fgets会读取换行符,fputs不会自动添加换行符。
- 读取失败时fgets返回NULL。
3. 二进制文件的读写操作
二进制文件以字节为单位读写,适合存储结构体、图像等非文本数据。
使用函数:
- 读取数据块:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
- 写入数据块:
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
参数说明:
- ptr:缓冲区指针
- size:每个元素大小(字节)
- nmemb:元素个数
- stream:文件指针
返回值为实际读写的元素个数。
示例:读写结构体数据时保证写入和读取的元素大小一致。
4. 文件读写中的定位操作
文件读写指针的位置可以通过以下函数控制:
int fseek(FILE *stream, long offset, int whence);- offset:偏移量
- whence:基准位置,常用值:SEEK_SET(文件开头), SEEK_CUR(当前位置), SEEK_END(文件末尾)
long ftell(FILE *stream);返回当前文件指针位置。void rewind(FILE *stream);将文件指针移至文件开头。
定位操作常用于随机访问文件中的数据。
5. 文件读写的错误处理
读写操作可能失败,应通过返回值检测:
- 返回EOF或0表示失败或文件末尾
- 使用
ferror(FILE *stream)检测文件错误 - 使用
feof(FILE *stream)判断文件结束
良好的错误处理保证程序健壮性。
实例分析
实例一:文本文件写入与读取
#include <stdio.h>
int main() {
FILE *fp = fopen("test.txt", "w");
if (fp == NULL) {
perror("打开文件失败");
return 1;
}
fputs("Hello, C file IO!\n", fp);
fclose(fp);
fp = fopen("test.txt", "r");
if (fp == NULL) {
perror("打开文件失败");
return 1;
}
char buffer[100];
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
printf("读取内容:%s", buffer);
}
fclose(fp);
return 0;
}
分析:程序先以写模式打开文本文件,写入字符串后关闭文件。随后以读模式打开文件,逐行读取内容输出。体现了文本文件的基本读写流程。
实例二:二进制文件写入与读取结构体
#include <stdio.h>
typedef struct {
int id;
char name[20];
float score;
} Student;
int main() {
Student s1 = {1001, "张三", 95.5};
FILE *fp = fopen("student.dat", "wb");
if (!fp) {
perror("打开文件失败");
return 1;
}
fwrite(&s1, sizeof(Student), 1, fp);
fclose(fp);
Student s2;
fp = fopen("student.dat", "rb");
if (!fp) {
perror("打开文件失败");
return 1;
}
fread(&s2, sizeof(Student), 1, fp);
fclose(fp);
printf("学号:%d\n姓名:%s\n成绩:%.2f\n", s2.id, s2.name, s2.score);
return 0;
}
分析:演示如何将结构体写入二进制文件,并读取回来。保证了数据的完整性和精确性,适合复杂数据存储。
实例三:文件随机访问操作
#include <stdio.h>
int main() {
FILE *fp = fopen("numbers.bin", "wb+");
if (!fp) {
perror("打开文件失败");
return 1;
}
int nums[5] = {10, 20, 30, 40, 50};
fwrite(nums, sizeof(int), 5, fp);
// 定位到第三个整数位置
fseek(fp, 2 * sizeof(int), SEEK_SET);
int num;
fread(&num, sizeof(int), 1, fp);
printf("第三个数字是:%d\n", num);
fclose(fp);
return 0;
}
分析:利用fseek定位文件指针,实现对文件中指定位置数据的访问,展示随机访问文件的原理与方法。
常见误区
- 误区1:未检查文件打开是否成功
- 正确做法:打开文件后应判断返回的文件指针是否为NULL,避免空指针操作。
- 误区2:文本模式和二进制模式混用
- 正确做法:根据文件类型选择合适的打开模式,文本文件用"r"、"w",二进制文件用"rb"、"wb"。
- 误区3:未关闭文件导致资源泄漏
- 正确做法:文件操作完成后必须调用fclose关闭文件,释放资源。
- 误区4:fgets读取后未处理换行符
- 正确做法:读取字符串后如需去除换行符,应手动处理。
- 误区5:fread/fwrite参数错误
- 正确做法:确保size和nmemb参数正确,避免读写数据错位或数据不完整。
应用场景
- 文本数据存储:配置文件、日志文件等需要以文本形式保存和读取数据。
- 二进制数据处理:图像、音频、视频文件或结构化数据的存储与读取。
- 数据备份与恢复:程序运行中数据的保存与恢复,提高程序的可靠性。
- 文件内容的随机访问:数据库索引文件、快速定位某条记录。
- 跨程序数据传递:通过文件进行不同程序间数据交互。
知识拓展
- 标准I/O缓冲机制:了解缓冲区对文件读写效率的影响,掌握fflush刷新缓冲。
- 高级文件操作函数:如
fgetc与getc,fputc与putc的区别。 - 多文件操作:同时打开多个文件的注意事项。
- 文件与目录操作:文件重命名、删除及目录读写相关函数。
- 跨平台文件操作差异:文本文件换行符差异及二进制文件兼容问题。
总结回顾
本节系统讲解了C语言文件的读写操作,涵盖了文件的打开关闭、文本与二进制文件的读写函数、文件指针定位以及错误处理等内容。通过实用的代码示例,演示了文本文件写入读取、二进制文件结构体操作以及随机访问文件的典型应用。特别强调了常见误区及正确的操作规范,帮助考生避免基础错误。掌握本节内容,考生能够熟练实现文件数据的持久化存储与访问,为实际开发和考试奠定坚实基础。
本节核心知识点总结:
- 文件的打开模式和关闭操作
- 文本文件的字符与字符串读写函数
- 二进制文件的块读写函数fread和fwrite
- 文件指针的定位与获取函数fseek、ftell、rewind
- 文件读写中的错误检测与处理
- 文件操作中的常见错误及防范措施