C语言fseek与ftell函数详解:随机访问文件与大小获取实战

Cora
Cora
发布时间:2026-10-13| 2人浏览过
原创

掌握 C 语言中的 fseek 和 ftell 函数是实现高效文件随机访问的关键。fseek 允许开发者根据指定起点(文件头、当前位置或文件尾)调整文件指针位置,支持负数或正数偏移;ftell 则用于返回当前指针相对于文件首的字节偏移量,常用来获取文件总长度。结合使用这两个函数,可以灵活处理二进制数据修改、大文件动态内存读取等场景。

结果或目标

在实际开发中,顺序读写往往无法满足需求。例如需要更新记录文件的最后一条数据,或者在不加载整个文件的情况下一次性读取其内容。本指南将展示如何利用 fseek 精准定位以及如何利用 ftell 获取文件大小,从而完成这些任务。

准备条件

  • C 语言标准库:<stdio.h> 提供文件操作接口,<stdlib.h> 提供内存分配接口。
  • 文件模式:确保以二进制模式(如 "rb+", "wb")打开文件,特别是在处理结构体或精确字节偏移时,文本模式下的换行符转换可能导致偏移计算错误。
  • 数据类型:理解 long 类型用于表示偏移量和文件位置指示器返回值。

真实操作顺序

第1步:使用 fseek 修改文件指针位置

目的: 将文件指针移动到指定位置,以便进行非顺序读写(如覆盖特定位置的数据)。

入口: int fseek(FILE *stream, long offset, int whence);

动作说明:

  • stream:已打开的文件指针。
  • offset:偏移量。正数表示向文件末尾方向移动,负数表示向文件开头方向移动。
  • whence:起始基准点,常用常量包括:
    • SEEK_SET:文件开头。
    • SEEK_CUR:文件指针当前所在位置。
    • SEEK_END:文件末尾。

注意事项: 若执行成功返回 0;失败返回非 0 值。需要注意的是,即使偏移量超出文件物理边界(如末尾之后或开头之前),某些实现也可能返回 0 但不改变文件状态或产生未定义行为,因此需谨慎使用。

第2步:在结构体文件中覆盖最后一条记录

场景: 假设有一个存储学生信息的二进制文件,需要修改最后一条学生的成绩而不影响其他数据。

操作步骤:

  1. 打开文件为读写模式:fopen("student.dat", "rb+")。
  2. 使用 fseek 定位到倒数一个结构体的位置:fseek(fp, -1L * sizeof(STU), SEEK_END)。这里从文件末尾往前偏移一个结构体的大小。
  3. 使用 fwrite 写入新数据覆盖旧数据。
  4. 关闭文件。
#include <stdio.h>
#define N 5
typedef struct student {
    long sno;
    char name[10];
    float score[3];
} STU;

void updateLastRecord(char* filename, STU n) {
    FILE* fp;
    // 以二进制读写模式打开
    fp = fopen(filename, "rb+");
    if (fp == NULL) return;
    
    // 关键步骤:定位到最后一个记录
    fseek(fp, -1L * sizeof(STU), SEEK_END);
    
    // 覆盖写入
    fwrite(&n, sizeof(STU), 1, fp);
    fclose(fp);
}

int main() {
    STU students[N] = {
        {10001, "MaChao", {91, 92, 77}},
        {10002, "CaoKai", {75, 60, 88}},
        {10003, "LiSi", {85, 70, 78}},
        {10004, "FangFang", {90, 82, 87}},
        {10005, "ZhangSan", {95, 80, 88}}
    };
    STU newStudent = {10006, "ZhaoSi", {55, 70, 68}};
    
    // 1. 创建测试文件
    FILE* fp = fopen("student.dat", "wb");
    fwrite(students, sizeof(STU), N, fp);
    fclose(fp);
    
    // 2. 执行覆盖操作
    updateLastRecord("student.dat", newStudent);
    
    // 3. 验证结果:重新读取并打印
    printf("Data after modification:\n");
    fp = fopen("student.dat", "rb");
    STU buffer[N];
    fread(buffer, sizeof(STU), N, fp);
    fclose(fp);
    
    for (int i = 0; i < N; i++) {
        printf("No: %ld, Name: %-8s, Scores: %.2f, %.2f, %.2f\n",
               buffer[i].sno, buffer[i].name, buffer[i].score[0],
               buffer[i].score[1], buffer[i].score[2]);
    }
    return 0;
}

第3步:使用 ftell 获取当前文件指针位置

目的: 确定文件指针当前距离文件开头的字节数,常用于获取文件大小或调试定位。

入口: long ftell(FILE *stream);

动作说明: 该函数返回当前文件位置指示器的值。对于二进制文件,这通常等于文件的绝对偏移量(字节数)。

第4步:结合 fseek 和 ftell 读取整个文本文件

场景: 动态分配内存以一次性读取整个文本文件内容,避免多次 realloc。

操作步骤:

  1. 以只读方式打开文件:fopen("1.txt", "r")。
  2. 将指针移动到文件末尾:fseek(fp, 0L, SEEK_END)。
  3. 使用 ftell 获取文件大小:flen = ftell(fp)。
  4. 分配内存:p = malloc(flen + 1)(预留 \0 结束符空间)。
  5. 将指针重置到文件开头:fseek(fp, 0L, SEEK_SET)。
  6. 一次性读取全部内容:fread(p, flen, 1, fp)。
  7. 添加字符串结束符 p[flen] = '\0'。
#include <stdio.h>
#include <stdlib.h>

int readFileIntoBuffer(const char* filename) {
    FILE* fp;
    long flen;
    char* p;

    if ((fp = fopen(filename, "r")) == NULL) {
        printf("File open error\n");
        return -1;
    }

    // 1. 定位到末尾获取大小
    fseek(fp, 0L, SEEK_END);
    flen = ftell(fp);
    
    // 异常检查:如果文件无法获取位置或为空处理
    if (flen <= 0) {
        fclose(fp);
        return -1;
    }

    // 2. 分配内存
    p = (char*)malloc(flen + 1);
    if (p == NULL) {
        fclose(fp);
        return -1;
    }

    // 3. 回到开头读取
    fseek(fp, 0L, SEEK_SET);
    fread(p, flen, 1, fp);
    p[flen] = '\0'; // 确保是合法C字符串

    printf("%s\n", p);

    // 4. 清理
    free(p);
    fclose(fp);
    return 0;
}

简要总结

fseek 提供了对文件内部任意位置的精确控制权,配合 SEEK_END 可轻松实现基于文件长度的反向寻址;ftell 则是测量“路径”长度的工具。两者结合,不仅能让二进制数据修改更高效,也能简化大文本文件的内存读取逻辑。在实际编程中,务必注意文件模式(二进制 vs 文本)对字节计数的影响,并在操作前做好资源释放检查。

以上就是C语言中fseek函数和ftell函数的详细内容,更多关于C语言文件操作的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。