前言:
在前几个章节讲解字符读写函数,字符串读写函数,格式化输入输出函数以及scanf,fscanf,sscanf,和s(f)printf。
在本章讲解文件随机读取
一·文件的随机读取
1·fseek
函数
fseek
函数用于定位文件内容的光标,通过偏移量从文件开头、当前位置或文件尾开始计算光标位置。其函数原型如下:
int fseek(FILE *stream, long offset, int whence);
stream
:文件指针。offset
:位移量,表示移动的字节数。whence
:起始点,可以是以下三个值之一:SEEK_SET
:文件开头。SEEK_CUR
:当前位置。SEEK_END
:文件尾。
例子:
#include <stdio.h>int main()
{FILE* fp = fopen("example.txt", "w+");if (fp == NULL){perror("打开文件失败");return 1;}// 写入一些内容fputs("这是C语言文件操作示例", fp);// 移动到第6个字节处(跳过"这是C语")fseek(fp, 9, SEEK_SET);// 从当前位置开始写入fputs("编程", fp);// 关闭前重置指针位置并输出内容rewind(fp);char buffer[100];fgets(buffer, sizeof(buffer), fp);printf("修改后的内容: %s\n", buffer); // 输出: 这是C语言编程操作示例fclose(fp);return 0;
}
2·ftell
函数
ftell
函数返回当前文件光标到文件开头的偏移量,用于计算文件大小。其函数原型如下:
long ftell(FILE *stream);
例子:
#include <stdio.h>int main()
{FILE* fp = fopen("data.txt", "r");if (fp == NULL){perror("打开文件失败");return 1;}// 获取初始位置long pos = ftell(fp);printf("初始位置: %ld\n", pos); // 0// 读取一些数据char ch;for (int i = 0; i < 5; i++){ch = fgetc(fp);if (ch == EOF) break;printf("%c", ch);}// 获取当前位置pos = ftell(fp);printf("\n当前位置: %ld\n", pos); // 5fclose(fp);return 0;
}
3·rewind
函数
rewind
函数将文件中的指针位置重置到文件开头,便于重新读写。其函数原型如下:
void rewind(FILE *stream);
例子:
#include <stdio.h>int main()
{FILE* fp = fopen("test.txt", "r+");if (fp == NULL) {perror("打开文件失败");return 1;}// 读取并显示第一行char line[100];fgets(line, sizeof(line), fp);printf("第一行: %s", line);// 重置到文件开头rewind(fp);// 再次读取第一行fgets(line, sizeof(line), fp);printf("再次读取第一行: %s", line);fclose(fp);return 0;
}
二·文件读取结束的判断
在进行文件读取时,需要判断何时到达文件末尾或发生错误。C语言提供了feof
和ferror
函数来帮助我们完成这一任务。
1·feof
函数
feof
函数用于判断文件是否处于结束位置。需要注意的是,feof
函数不能直接用于判断文件是否读取结束,而是在读取操作之后使用,以确定读取结束的原因是否是遇到文件尾。其函数原型如下:
int feof(FILE *stream);
例子:
#include <stdio.h>int main()
{FILE* fp = fopen("numbers.txt", "r");if (fp == NULL) {perror("打开文件失败");return 1;}int num;printf("读取到的数字:\n");while (1){fscanf(fp, "%d", &num);if (feof(fp)){printf("\n已到达文件末尾\n");break;}printf("%d ", num);// 检查错误if (ferror(fp)) {perror("读取错误");break;}}fclose(fp);return 0;
}
2·ferror
函数
ferror
函数用于检查文件读写是否出错。其函数原型如下:
int ferror(FILE *stream);
例子:
#include <stdio.h>int main()
{FILE *fp = fopen("nonexistent.txt", "r");if (fp == NULL)
{perror("打开文件失败");return 1;
}// 故意制造错误(尝试写入只读模式打开的文件)fputc('A', fp);if (ferror(fp))
{printf("检测到错误!\n");perror("错误详情");// 清除错误标志clearerr(fp);printf("错误标志已清除\n");if (!ferror(fp))
{printf("现在没有错误\n");}}fclose(fp);return 0;
}
3. 判断文件结束的原因示例
通过feof
和ferror
函数结合使用,可以判断文件读取是否正常或因错误而结束。以下是一些常见的判断方法:
-
文本文件是否读取结束:
- 判断函数
fgetc
的返回值是否为EOF
。 - 判断函数
fgets
的返回值是否为NULL
。
- 判断函数
-
二进制文件是否读取结束:
- 判断函数
fread
返回的实际读取元素个数是否小于预期值。
- 判断函数
示例代码如下:
#include <stdio.h>int main() {char arr[20];FILE* pf = fopen("test.txt", "r");if (pf == NULL) {perror("fopen");return 1;}fgets(arr, 20, pf);printf("%s\n", arr);if (feof(pf)) {printf("文件正常读取结束\n");}if (ferror(pf)) {printf("文件错误读取结束\n");perror("读取失败原因");}fclose(pf);return 0;
}
三·文件缓冲区
文件缓冲区是ANSIC标准中采用的“缓冲文件系统”,用于在内存中为程序中每个正在使用的文件开辟一块缓冲区,以提高数据读写效率。当缓冲区装满或文件被关闭时,缓冲区中的数据会自动刷新并写入文件。fflush
函数可以随时刷新缓冲区,使缓冲区中的数据立即写入文件。
1. 缓冲区的工作原理
- 全缓冲:当缓冲区满时,数据被刷新到磁盘。
- 行缓冲:当遇到换行符时,数据被刷新到磁盘。
- 无缓冲:数据直接写入磁盘,不使用缓冲区。
2. fflush
函数
fflush
函数用于刷新指定文件流的输出缓冲区。其函数原型如下:
int fflush(FILE *stream);
如果stream
为NULL
,则刷新所有打开的输出流。
3. 示例代码
#include <stdio.h>int main() {FILE* pf = fopen("test.txt", "w");if (pf == NULL) {perror("fopen");return 1;}fprintf(pf, "Hello, World!\n");fflush(pf); // 刷新缓冲区fclose(pf);return 0;
}
总结:
本章节详细介绍了C语言中文件的随机读取、文件读取结束的判定以及文件缓冲区
通过使用fseek
、ftell
和rewind
函数,可以实现文件的随机访问;通过feof
和ferror
函数,可以准确判断文件读取的状态;而文件缓冲区则通过在内存中暂存数据来提高文件操作的效率。
本章结束了!!!
我们下章再见!!