C fseek 函数
最后修改日期:2025 年 4 月 6 日
在 C 编程中,文件定位对于高效的文件处理至关重要。fseek 函数允许在文件内进行精确导航,实现随机访问操作。本教程将深入讲解 fseek,涵盖其参数、返回值和实际应用。通过八个详细示例,您将掌握文本文件和二进制文件的文件定位。理解 fseek 可以提升您处理大文件和复杂数据结构的能力。
什么是 fseek?
C 中的 fseek 函数将文件指针重新定位到文件内的特定位置。它接受三个参数:一个 FILE 指针,一个长整型偏移量,以及一个起始点指定符。起始点可以是 SEEK_SET(开头)、SEEK_CUR(当前)或 SEEK_END(结尾)。fseek 成功时返回 0,失败时返回非零值。它适用于文本文件和二进制文件,但行为在两者之间可能略有不同。
fseek 基本语法
fseek 函数的原型直接但功能强大。
int fseek(FILE *stream, long offset, int whence);
stream 参数是 fopen 返回的文件指针。offset 指定要移动的字节数,可以是正数或负数。whence 确定偏移量的参考点。始终检查返回值以确保操作成功。适当的错误处理可以防止文件操作中出现意外行为。
移动到特定位置
此示例演示如何跳转到文件中的特定位置。
#include <stdio.h>
int main() {
FILE *fp = fopen("data.txt", "r");
if (fp == NULL) {
perror("Error opening file");
return 1;
}
// Move to 10th byte from beginning
if (fseek(fp, 10, SEEK_SET)) {
perror("Error seeking file");
fclose(fp);
return 1;
}
int ch = fgetc(fp);
printf("Character at position 10: %c\n", ch);
fclose(fp);
return 0;
}
在此,fseek 将文件指针定位到距离开头(SEEK_SET)10 个字节的位置。然后我们读取并打印该位置的字符。错误处理确保我们捕获文件操作中的任何问题。此技术对于访问固定长度文件中的特定记录很有用。请记住,操作完成后要关闭文件。
从当前位置搜索
通过此示例了解如何相对于当前文件位置进行移动。
#include <stdio.h>
int main() {
FILE *fp = fopen("data.txt", "r");
if (fp == NULL) {
perror("Error opening file");
return 1;
}
// Read first character
int ch1 = fgetc(fp);
printf("First character: %c\n", ch1);
// Move 5 bytes forward from current position
if (fseek(fp, 5, SEEK_CUR)) {
perror("Error seeking file");
fclose(fp);
return 1;
}
int ch2 = fgetc(fp);
printf("Character after skipping 5: %c\n", ch2);
fclose(fp);
return 0;
}
读取第一个字符后,使用 SEEK_CUR 的 fseek 将指针向前移动 5 个字节。这种相对定位在处理可变长度记录的文件时非常有用。该示例展示了如何从当前位置跳过。在继续读取或写入之前,请务必验证搜索操作是否成功。
从文件末尾搜索
此示例演示如何相对于文件末尾定位文件指针。
#include <stdio.h>
int main() {
FILE *fp = fopen("data.txt", "r");
if (fp == NULL) {
perror("Error opening file");
return 1;
}
// Move to 5 bytes before end
if (fseek(fp, -5, SEEK_END)) {
perror("Error seeking file");
fclose(fp);
return 1;
}
printf("Last 5 characters:\n");
int ch;
while ((ch = fgetc(fp)) != EOF) {
putchar(ch);
}
fclose(fp);
return 0;
}
使用带负偏移量的 SEEK_END 将指针定位到文件末尾之前。在这里,我们读取并显示最后 5 个字符。此技术非常适合检查文件尾部或页脚。负偏移量仅在 SEEK_END 和 SEEK_CUR 中有效。该示例包含健全的错误处理,可用于生产质量的代码。
使用 fseek 查找文件大小
结合使用 fseek 和 ftell 来确定文件的大小。
#include <stdio.h>
int main() {
FILE *fp = fopen("data.txt", "r");
if (fp == NULL) {
perror("Error opening file");
return 1;
}
// Seek to end
if (fseek(fp, 0, SEEK_END)) {
perror("Error seeking file");
fclose(fp);
return 1;
}
// Get position (file size)
long size = ftell(fp);
printf("File size: %ld bytes\n", size);
fclose(fp);
return 0;
}
移动到文件末尾并调用 fseek,然后调用 ftell 可以显示文件的大小(以字节为单位)。此方法适用于文本文件和二进制文件。大小表示从开头到结尾位置的偏移量。请记住,对于非常大的文件,在某些系统上您可能需要使用 fseeko 和 ftello。如果您在检查文件大小后需要读取文件,请始终重置指针。
修改文件内容
使用 fseek 以读写模式更新文件的特定部分。
#include <stdio.h>
int main() {
FILE *fp = fopen("data.txt", "r+");
if (fp == NULL) {
perror("Error opening file");
return 1;
}
// Move to 10th byte
if (fseek(fp, 10, SEEK_SET)) {
perror("Error seeking file");
fclose(fp);
return 1;
}
// Overwrite character
fputc('X', fp);
fclose(fp);
printf("File modified successfully.\n");
return 0;
}
以 "r+" 模式打开允许读写。fseek 将指针定位到第 10 字节,然后 fputc 在该位置写入一个 'X'。此方法非常适合进行有针对性的更改,而无需重写整个文件。确保在以 "r+" 模式打开文件之前文件存在。刷新或关闭文件可确保更改已保存到磁盘。
二进制文件随机访问
使用 fseek 随机访问二进制文件中的记录。
#include <stdio.h>
struct Record {
int id;
char name[20];
float value;
};
int main() {
FILE *fp = fopen("data.bin", "rb+");
if (fp == NULL) {
perror("Error opening file");
return 1;
}
// Read 3rd record (0-based index)
if (fseek(fp, 2 * sizeof(struct Record), SEEK_SET)) {
perror("Error seeking file");
fclose(fp);
return 1;
}
struct Record rec;
fread(&rec, sizeof(struct Record), 1, fp);
printf("Record 3: ID=%d, Name=%s, Value=%.2f\n",
rec.id, rec.name, rec.value);
fclose(fp);
return 0;
}
此示例演示了包含固定大小记录的二进制文件的随机访问。fseek 通过计算偏移量直接跳转到第三条记录。二进制模式 ("rb+") 可确保精确的定位和数据表示。此技术对于类似数据库的操作至关重要。在计算偏移量时,请始终使用 sizeof 以确保可移植性。
fseek 的错误处理
正确处理错误可确保在使用 fseek 进行文件操作时具有健壮性。
#include <stdio.h>
int main() {
FILE *fp = fopen("data.txt", "r");
if (fp == NULL) {
perror("Error opening file");
return 1;
}
// Attempt invalid seek
if (fseek(fp, -100, SEEK_SET)) {
perror("Seek error");
printf("Attempted to seek before file start\n");
}
// Attempt valid seek
if (fseek(fp, 100, SEEK_SET) == 0) {
printf("Seek successful\n");
if (ftell(fp) == 100) {
printf("Position verified\n");
}
}
fclose(fp);
return 0;
}
此示例展示了如何优雅地处理 fseek 错误。尝试在文件开头之前进行搜索将失败,而有效的搜索则会成功。ftell 函数用于验证新位置。全面的错误检查可防止崩溃和数据损坏。在处理文件定位时,始终测试边界情况。
使用 fseek 的最佳实践
- 检查返回值:始终验证
fseek是否返回 0 表示成功。 - 使用二进制模式以提高精度:文本模式可能会更改换行符,从而影响定位。
- 与 ftell 结合使用:在搜索后使用
ftell来验证位置。 - 小心处理大文件:在某些系统上,请考虑对大于 2GB 的文件使用
fseeko。 - 在需要时重置位置:使用
rewind或fseek返回到开头。
来源
本教程通过八个实际示例探讨了多功能的 fseek 函数。从基本定位到二进制文件访问,您现在已经掌握了高效导航文件的工具。掌握 fseek 可以使您的 C 程序实现复杂的文件处理。
作者
列表 C 标准库。