程序员求职经验分享与学习资料整理平台

网站首页 > 文章精选 正文

C语言fseek函数详解:“文件时光机”

balukai 2025-03-26 09:42:02 文章精选 11 ℃

一句话理解 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 是操作文件的「时光遥控器」
最近发表
标签列表