C ferror 函数
最后修改日期:2025 年 4 月 6 日
为确保程序可靠性,错误处理在文件操作中至关重要。ferror 函数有助于检测文件 I/O 操作中的错误。本教程通过实际示例深入讲解 ferror。您将学会如何检查文件操作错误并妥善处理它们。掌握 ferror 能使 C 程序中的文件处理更加健壮。
什么是 ferror?
ferror 函数检查文件操作中是否发生错误。它以 FILE 指针作为唯一参数。如果检测到错误,该函数将返回非零值。与检查文件结束的 feof 不同,ferror 专门检测读/写错误。在使用文件流之前,务必使用 clearerr 清除错误。
ferror 的基本用法
此示例演示了使用 ferror 检查文件操作错误的最简单方法。
#include <stdio.h>
int main() {
FILE *fp = fopen("nonexistent.txt", "r");
if (fp == NULL) {
perror("File opening failed");
return 1;
}
// Attempt to read from file
int ch = fgetc(fp);
if (ferror(fp)) {
perror("Error reading file");
clearerr(fp); // Clear the error flag
}
fclose(fp);
return 0;
}
此代码尝试打开一个可能不存在的文件并从中读取。读取操作后,ferror 检查是否发生了错误。clearerr 函数会重置错误标志,以便后续操作。请注意,我们仍然单独检查 fopen,因为它直接设置 errno。
写操作后检查 ferror
ferror 也可以检测写操作中的错误,如本示例所示。
#include <stdio.h>
int main() {
FILE *fp = fopen("/readonly/test.txt", "w");
if (fp == NULL) {
perror("File opening failed");
return 1;
}
// Attempt to write to a potentially read-only location
fprintf(fp, "Test data");
if (ferror(fp)) {
perror("Error writing to file");
clearerr(fp);
}
fclose(fp);
return 0;
}
在此,我们尝试将内容写入可能位于只读位置的文件。写操作尝试后,ferror 检查操作是否成功。错误消息有助于诊断权限问题。为进行全面的错误处理,请务必同时检查 fopen 和 ferror。
ferror 在文件复制程序中的应用
此示例展示了 ferror 在实际文件复制应用程序中的用法。
#include <stdio.h>
int main() {
FILE *src = fopen("source.txt", "r");
FILE *dest = fopen("destination.txt", "w");
if (src == NULL || dest == NULL) {
perror("File opening failed");
return 1;
}
int ch;
while ((ch = fgetc(src)) != EOF) {
fputc(ch, dest);
if (ferror(src) || ferror(dest)) {
perror("File operation error");
clearerr(src);
clearerr(dest);
break;
}
}
fclose(src);
fclose(dest);
return 0;
}
该程序将内容从 source.txt 复制到 destination.txt。每次字符传输后,ferror 都会检查两个文件是否存在错误。如果发生错误,循环将立即中断。这确保我们能检测到复制过程中出现的磁盘已满等问题。
使用 ferror 处理二进制文件
二进制文件操作也可从 ferror 检查中受益,如本示例所示。
#include <stdio.h>
int main() {
FILE *fp = fopen("data.bin", "rb");
if (fp == NULL) {
perror("File opening failed");
return 1;
}
int data[10];
size_t read = fread(data, sizeof(int), 10, fp);
if (read != 10 && ferror(fp)) {
perror("Error reading binary data");
clearerr(fp);
}
fclose(fp);
return 0;
}
此代码从二进制文件中读取一个整数数组。在 fread 之后,我们同时检查返回值和 ferror。这两者结合起来可以确保我们同时检测到 EOF 和实际的读取错误。由于二进制操作的敏感性,它们通常需要这种级别的错误检查。
ferror 与临时文件
临时文件也可能遇到 ferror 可以检测到的错误。
#include <stdio.h>
int main() {
FILE *tmp = tmpfile();
if (tmp == NULL) {
perror("Temporary file creation failed");
return 1;
}
for (int i = 0; i < 100; i++) {
fprintf(tmp, "Line %d\n", i);
if (ferror(tmp)) {
perror("Error writing to temp file");
clearerr(tmp);
break;
}
}
fclose(tmp);
return 0;
}
该程序创建一个临时文件并向其中写入 100 行。每次写入后,ferror 都会检查错误。临时文件可能由于磁盘空间或权限问题而失败。定期的错误检查可确保我们在过程早期就捕获这些问题。
ferror 在网络文件操作中的应用
网络挂载的文件系统可能需要使用 ferror 进行额外的错误检查。
#include <stdio.h>
#include <unistd.h>
int main() {
FILE *fp = fopen("/mnt/network/share/file.txt", "r");
if (fp == NULL) {
perror("Network file opening failed");
return 1;
}
char buffer[256];
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
printf("%s", buffer);
if (ferror(fp)) {
perror("Network read error");
clearerr(fp);
sleep(1); // Wait before retrying
}
}
fclose(fp);
return 0;
}
网络文件可能因连接问题而间歇性失败。此代码从网络文件中读取数据并进行错误检查。当 ferror 检测到问题时,它会等待片刻再继续。这种模式有助于在文件操作中更优雅地处理暂时的网络故障。
ferror 的高级用法与 errno
将 ferror 与 errno 结合使用,以进行详细的错误诊断。
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main() {
FILE *fp = fopen("important.dat", "r+");
if (fp == NULL) {
perror("File opening failed");
return 1;
}
// Critical file operation
if (fseek(fp, 1024, SEEK_SET) != 0 || ferror(fp)) {
fprintf(stderr, "Seek error: %s\n", strerror(errno));
clearerr(fp);
}
// Data processing would continue here
fclose(fp);
return 0;
}
此示例展示了结合使用 ferror 和 errno 的高级错误处理。在文件定位操作之后,我们同时检查返回值和 ferror。strerror 函数提供详细的错误消息。对于需要精确错误信息的关键文件操作,这种方法非常有用。
使用 ferror 的最佳实践
- 每次操作后检查:在关键的文件 I/O 操作后使用
ferror。 - 与其他检查结合:与返回值检查结合使用,以实现全面的错误处理。
- 正确清除错误:在适当的时候使用
clearerr重置错误标志。 - 提供上下文:在错误消息中包含文件/操作的详细信息。
- 考虑错误恢复:尽可能为短暂性错误实现重试逻辑。
来源
本教程演示了 ferror 在健壮的文件处理中的重要性。从基本检查到网络文件场景,正确的错误检测可防止数据损坏并提高可靠性。采用这些技术可以使您的文件操作更具韧性。
作者
列表 C 标准库。