一句话理解 fseek
「在文件的‘时间线’上自由穿梭,精准定位到任意字节位置,实现随机读写!」
函数原型
#include // 必须包含头文件
int fseek(FILE *stream, long offset, int whence);
入口参数
参数 | 类型 | 比喻解释 |
stream | FILE* | 文件「时光机」的控制台(文件指针) |
offset | long | 时间跳跃的「步数」(字节偏移量) |
whence | int | 时间旅行的「起点」(定位基准) |
定位基准(whence参数)
宏定义 | 值 | 比喻解释 |
SEEK_SET | 0 | 从文件开头出发(时光起点) |
SEEK_CUR | 1 | 从当前位置出发(现在时刻) |
SEEK_END | 2 | 从文件末尾出发(未来终点) |
返回参数
返回值 | 含义 |
0 | 时光穿梭成功 |
非0 | 穿梭失败(如超出文件范围) |
核心功能图解
文件内容:A B C D E F G H I J
调用 fseek(file, 3, SEEK_SET) → 定位到第3字节(D)
调用 fseek(file, -2, SEEK_END) → 定位到倒数第2字节(I)
代码实例1:读取文件的特定片段
场景:直接读取文件的中间内容(类似快速翻书)
#include
int main() {
FILE *file = fopen("story.txt", "rb"); // 二进制模式避免换行符干扰
if (!file) {
perror(" 故事书打不开");
return 1;
}
// 时光穿梭:跳到第100字节处(跳过前言)
if (fseek(file, 100, SEEK_SET) != 0) {
printf(" 穿梭失败,可能故事太短\n");
fclose(file);
return 1;
}
char buffer[256];
size_t read = fread(buffer, 1, sizeof(buffer), file);
if (read > 0) {
printf("从第100字节开始的故事片段:\n%.*s\n", (int)read, buffer);
}
fclose(file);
return 0;
}
代码实例2:逆向读取文件
场景:从文件末尾逐字节向前读取
#include
int main() {
FILE *file = fopen("message.txt", "rb");
if (!file) {
perror(" 密文失窃");
return 1;
}
// 定位到文件末尾
fseek(file, 0, SEEK_END);
long file_size = ftell(file); // 获取文件总大小
// 从后往前逐个字符读取
for (long i = 1; i <= file_size; i++) {
fseek(file, -i, SEEK_END); // 时光倒流i步
char c = fgetc(file);
putchar(c);
}
fclose(file);
return 0;
}
技术细节剖析
1.偏移量的正负规则
基准点 | 正偏移量 | 负偏移量 |
SEEK_SET | 向文件末尾移动 | 非法(可能崩溃) |
SEEK_CUR | 向前移动 | 向后移动 |
SEEK_END | 通常非法 | 向前回溯 |
2.二进制模式 vs 文本模式
- 在Windows系统中,文本模式的文件换行符会被转换,导致偏移量计算错误:
// 错误示范:文本模式下定位
FILE *file = fopen("data.txt", "r"); // 换行符会被转换
fseek(file, 10, SEEK_SET); // 实际位置可能不准确
3.与 ftell 的黄金组合
// 记录当前位置
long pos = ftell(file);
// ...其他操作后
fseek(file, pos, SEEK_SET); // 回到记录的位置
致命误区
1.定位到无效位置
FILE *file = fopen("empty.txt", "r");
fseek(file, 100, SEEK_SET); // 文件为空,定位失败!
2.忘记刷新缓冲区
fprintf(file, "Hello");
fseek(file, 0, SEEK_SET); // 写操作后直接定位,缓冲区可能未刷新
高级技巧:快速获取文件大小
FILE *file = fopen("bigfile.bin", "rb");
fseek(file, 0, SEEK_END); // 时光机飞到终点
long size = ftell(file); // 记录终点位置
printf("文件大小:%ld 字节\n", size);
fseek(file, 0, SEEK_SET); // 回到起点
对比 rewind
操作 | 功能 | 是否重置错误标志 |
fseek(file, 0, SEEK_SET) | 回到文件起点 | 否 |
rewind(file) | 回到文件起点 + 清除错误标志 | 是 |
总结
- 核心功能:精确定位文件指针位置
- 必用场景:数据库索引、文件格式解析、日志回查
- 类比记忆:就像DVD播放器的快进/快退按钮,fseek 是操作文件的「时光遥控器」