ZetCode

C ftell 函数

最后修改日期:2025 年 4 月 6 日

文件位置跟踪对于 C 编程中的高效文件处理至关重要。ftell 函数有助于确定文件流中当前的位置。本教程将深入解释 ftell,通过实用示例演示其用法,并提供最佳实践。掌握文件位置跟踪可实现程序中精确的文件操作和更好的错误处理。

什么是 ftell?

C 中的 ftell 函数返回给定流的当前文件位置指示器。它以 FILE 指针作为唯一参数,并返回一个代表该位置的 long 值。对于二进制流,此值是从开头开始的字节数。对于文本流,该值是实现定义的,但对于 fseek 很方便。始终检查错误,因为 ftell 在失败时返回 -1L。

基本 ftell 用法

此示例展示了使用 ftell 获取当前文件位置的最简单方法。

basic_ftell.c
#include <stdio.h>

int main() {
    FILE *fp = fopen("example.txt", "r");
    if (fp == NULL) {
        perror("Error opening file");
        return 1;
    }

    long position = ftell(fp);
    printf("Initial position: %ld\n", position);

    fclose(fp);
    return 0;
}

此代码打开一个文件并立即使用 ftell 检查其位置。新打开文件的初始位置通常为 0。打印位置,然后关闭文件。如果文件无法打开,错误处理可确保程序优雅地失败。

读取时跟踪位置

此示例演示了 ftell 在读取文件时如何跟踪位置变化。

read_tracking.c
#include <stdio.h>

int main() {
    FILE *fp = fopen("data.txt", "r");
    if (fp == NULL) {
        perror("Error opening file");
        return 1;
    }

    int ch;
    while ((ch = fgetc(fp)) != EOF) {
        long pos = ftell(fp);
        printf("Read '%c' at position %ld\n", ch, pos);
    }

    fclose(fp);
    return 0;
}

程序在打印字符及其位置的同时读取文件中的每个字符。每次读取后都会调用 ftell 以获取更新后的位置。这显示了位置如何随着每次读取操作而增加。循环一直持续到遇到 EOF

将 ftell 与 fseek 结合使用

此示例展示了 ftellfseek 如何协同工作以实现随机文件访问。

ftell_fseek.c
#include <stdio.h>

int main() {
    FILE *fp = fopen("records.txt", "r+");
    if (fp == NULL) {
        perror("Error opening file");
        return 1;
    }

    // Get current position
    long start_pos = ftell(fp);
    printf("Start position: %ld\n", start_pos);

    // Move to end and get position
    fseek(fp, 0, SEEK_END);
    long end_pos = ftell(fp);
    printf("End position: %ld\n", end_pos);

    // Return to start
    fseek(fp, 0, SEEK_SET);

    fclose(fp);
    return 0;
}

该程序演示了如何将 ftellfseek 结合使用来导航文件。它首先获取起始位置,然后移动到文件末尾以获取文件大小。最后,它返回到开头。此模式对于确定文件大小和重置位置很有用。

二进制文件位置跟踪

此示例展示了 ftell 在二进制文件中的用法,其中位置直接对应于字节偏移量。

binary_ftell.c
#include <stdio.h>

int main() {
    FILE *fp = fopen("data.bin", "rb");
    if (fp == NULL) {
        perror("Error opening file");
        return 1;
    }

    // Read first integer
    int value;
    fread(&value, sizeof(int), 1, fp);
    long pos = ftell(fp);
    printf("After reading first int: position %ld\n", pos);

    // Skip next two integers
    fseek(fp, 2 * sizeof(int), SEEK_CUR);
    pos = ftell(fp);
    printf("After skipping two: position %ld\n", pos);

    fclose(fp);
    return 0;
}

对于二进制文件,ftell 返回精确的字节偏移量。程序读取一个整数(通常为 4 字节),然后跳过另外两个。显示每次操作对位置的影响。这演示了二进制文件位置如何直接对应于字节计数。

ftell 的错误处理

此示例演示了使用 ftell 时的正确错误处理。

ftell_error.c
#include <stdio.h>

int main() {
    FILE *fp = fopen("nonexistent.txt", "r");
    if (fp == NULL) {
        perror("Error opening file");
        return 1;
    }

    // Force an error by closing the stream
    fclose(fp);
    long pos = ftell(fp);

    if (pos == -1L) {
        perror("ftell failed");
        return 1;
    }

    return 0;
}

该程序通过在已关闭的文件流上调用 ftell 来故意创建错误条件。这显示了如何检查 ftell 故障(返回 -1L)。正确的错误处理可防止未定义行为并有助于调试问题。在可能出错时,请务必检查 ftell 的返回值。

文本文件位置注意事项

此示例重点介绍了在文本文件中使用 ftell 时的特殊注意事项。

text_ftell.c
#include <stdio.h>

int main() {
    FILE *fp = fopen("textfile.txt", "r");
    if (fp == NULL) {
        perror("Error opening file");
        return 1;
    }

    // Read first line
    char buffer[100];
    fgets(buffer, sizeof(buffer), fp);
    long pos = ftell(fp);
    printf("Position after first line: %ld\n", pos);

    // For text files, positions are only reliable with fseek
    fseek(fp, 0, SEEK_SET);
    pos = ftell(fp);
    printf("Position after rewind: %ld\n", pos);

    fclose(fp);
    return 0;
}

对于文本文件,ftell 的位置是实现定义的,但在与 fseek 结合使用时是一致的。程序读取一行并显示其位置,然后倒回以演示位置重置。虽然文本位置不是字节计数,但它们可以可靠地用于返回到标记的位置。

大文件支持

此示例使用 ftello 替代项演示了 ftell 对大文件的使用。

large_ftell.c
#define _FILE_OFFSET_BITS 64
#include <stdio.h>

int main() {
    FILE *fp = fopen("largefile.bin", "rb");
    if (fp == NULL) {
        perror("Error opening file");
        return 1;
    }

    // Move to end to get size
    fseeko(fp, 0, SEEK_END);
    off_t size = ftello(fp);
    printf("File size: %lld bytes\n", (long long)size);

    fclose(fp);
    return 0;
}

对于大于 2GB 的文件,建议使用 ftello(带有 off_t)而不是 ftell。该程序演示了如何获取大文件的文件大小。_FILE_OFFSET_BITS 宏可确保 64 位文件操作。这对于处理大型数据集的现代应用程序至关重要。

使用 ftell 的最佳实践

来源

C ftell 文档

本教程探讨了 C 语言中的 ftell 函数,演示了其在各种场景下的用法,从基本的位置跟踪到大文件处理。正确使用文件位置函数可为您的应用程序实现复杂的文件操作和错误处理。

作者

我的名字是 Jan Bodnar,我是一名敬业的程序员,对编程充满热情。自 2007 年以来,我通过 1,400 多篇文章和 8 本电子书分享了我的专业知识。凭借十多年的教学经验,我致力于让编程变得易于理解且引人入胜。

列表 C 标准库