学而时习之:C语言中文件操作Error处理

一. C 中的 ferror() 函数

在 C 语言中,ferror() 是一个内置函数,用于在文件操作期间检查文件是否发生错误。它提供了一种简单的方法,在你的 C 程序中进行文件操作时不会中断。


1.ferror 语法

ferror() 是一个标准库函数,定义在头文件 <stdio.h> 中。

c 复制代码
ferror(fptr)

**参数:**  
接收一个文件流指针作为参数。

**返回值:**  
- 如果文件有错误,返回一个非零值。  
- 否则,返回 0。

**注意:** 要使用 `ferror()` 检查文件错误,文件必须先打开。

2.ferror() 的示例


示例 1:写入数据时检查错误
c 复制代码
#include <stdio.h>

int main() {
    FILE *fptr = fopen("gfg.txt", "w");

    // 向文件写入数据
    fprintf(fptr, "Hello, GFG!");

    // 写入后检查是否有错误
    if (ferror(fptr) == 0)
        printf("数据写入成功。");
    
    fclose(fptr);
    return 0;
}

输出:

复制代码
数据写入成功。

示例 2:读取数据时检查错误
c 复制代码
#include <stdio.h>

int main() {
    FILE *fptr = fopen("gfg.txt", "w+");
    fprintf(fptr, "GeeksForGeeks!");

    rewind(fptr);

    char d[14];
    while (fscanf(fptr, "%s", d) != EOF)

    // 读取后检查是否有错误
    if (ferror(fptr) == 0) {
        for (int i = 0; i < sizeof(d); i++) {
            printf("%c", d[i]);
        }
        printf("\n没有错误,数据读取成功");
    }

    fclose(fptr);
    return 0;
}

输出:

复制代码
GeeksForGeeks!
没有错误,数据读取成功

二. C 中的 EOFgetc()feof()

1.什么是 EOF

在 C 中,EOF 是一个常量宏,定义在头文件 <stdio.h> 中,用于表示文件结束。它被多个文件读取函数使用,比如 fread()gets()getc() 等。 EOF 的值是由实现定义的,但通常是 -1


2.getc() 函数

getc() 函数用于从给定的文件流中读取一个字符。它是以宏的形式在 <stdio.h> 中实现的。

语法:

c 复制代码
getc(fptr);

#### 参数:
- `fptr`:指向要读取数据的文件流的指针。

#### 返回值:
- 返回从文件流中读取的字符。
- 如果发生错误或到达文件末尾,返回 `EOF`。

3.feof() 函数

feof() 函数用于检查文件指针是否指向文件末尾。如果到达文件末尾,它返回一个非零值;否则返回 0。

语法:

c 复制代码
feof(fptr);

#### 参数:
- `fptr`:指向要读取数据的文件流的指针。

#### 返回值:
- 如果到达文件末尾,返回非零值(通常是 1)。
- 否则返回 0。

4.为什么需要 feof()

getc() 在到达文件末尾时会返回 EOF,但它在读取失败时也会返回 EOF。因此,仅靠比较 getc() 的返回值和 EOF 并不足以判断是否真的到了文件末尾。为了解决这个问题,C 提供了 feof() 函数。


示例 1:无法区分错误还是文件结束

c 复制代码
#include <stdio.h>

int main() {
    FILE *fptr = fopen("file.txt", "w");
    char ch;

    // 尝试用 getc() 读取一个字符
    ch = getc(fptr);

    // 处理 EOF 返回值
    if (ch == EOF)
        printf("文件结束或无法读取");
    else
        printf("读取的字符:%c", ch);

    fclose(fptr);
    return 0;
}

输出:

复制代码
文件结束或无法读取

在上述程序中,文件是以"只写"模式打开的,getc() 无法读取数据,但它仍然返回 EOF,这使得我们难以判断错误的来源。此时可以使用 feof() 来明确判断是否到达文件末尾。


示例 2:使用 feof() 明确判断文件结束

c 复制代码
#include <stdio.h>

int main() {
    FILE *fptr = fopen("file.txt", "w");
    char ch;

    // 尝试用 getc() 读取一个字符
    ch = getc(fptr);

    // 处理 EOF 返回值
    if (ch == EOF) {
        // 检查是文件结束,还是读取失败
        if (feof(fptr))
            printf("文件结束");
        else
            printf("无法读取");
    } else
        printf("读取的字符:%c", ch);

    fclose(fptr);
    return 0;
}

输出:

复制代码
无法读取

三. C 中的 clearerr() 函数

在 C 语言中,文件操作中的错误可以通过 ferror()feof() 函数来检测。但这些错误标志一旦设置就会一直保留 ,直到被显式清除。clearerr() 是一个标准库函数,用于在你进行文件读写操作时手动清除这些错误标志

语法 : clearerr() 是定义在头文件 <stdio.h> 中的标准库函数。

c 复制代码
clearerr(fptr);
#### 参数:
- `fptr`:指向文件流的文件指针。

#### 返回值:
- 该函数**没有返回值**(`void`)。

示例 1:

c 复制代码
#include <stdio.h>

int main() {
    FILE *fptr = fopen("gfg.text", "rw+");

    // 清除错误和 EOF 标志
    clearerr(fptr);
    if (!feof(fptr))
        printf("EOF 重置成功");
    return 0;
}

输出:

复制代码
EOF 重置成功

示例 2:清除 EOF 标志的实际用法

c 复制代码
#include <stdio.h>

int main() {
    FILE *fptr = fopen("gfg.txt", "w+");
    fprintf(fptr, "GeeksForGeeks!");

    // 不断读取直到遇到 EOF
    while (fgetc(fptr) != EOF);

    if (feof(fptr)) {
        printf("遇到 EOF\n");
    }

    // 使用 clearerr() 清除 EOF 标志
    clearerr(fptr);
    if (!feof(fptr)) {
        printf("EOF 已成功重置");
    }

    fclose(fptr);
    return 0;
}

输出:

复制代码
遇到 EOF
EOF 已成功重置

总结:

  • clearerr() 用于清除文件流的错误标志和 EOF 标志
  • 它不会返回任何值,只是重置状态
  • 常用于重复读写文件调试文件操作时。

四. C 语言文件操作中的错误处理

文件操作是 C 编程中的常见任务,但可能遇到各种错误,需要优雅地处理。良好的错误处理能让程序在面对"文件缺失""权限不足"等突发情况时不至于崩溃。本文将学习如何在 C 语言文件操作中处理这些常见错误。

常见文件操作错误一览

错误 原因
文件未找到 试图打开一个不存在的文件
权限被拒绝 对文件访问权限不足
磁盘已满 写入时磁盘空间耗尽
文件已存在 用 "w" 模式创建已存在的文件
无效文件指针 使用 NULL 或非法 FILE* 进行读写
已到文件尾 (EOF) 读操作越过文件末尾
文件未打开 在未成功打开的文件上继续操作

若不做错误检查,程序可能出现异常行为:提前终止或输出错误结果。

错误处理技巧(不一定非要这么处理,只是简单建议,要灵活处理)

1. 处理 "文件未找到"

以只读 "r" 或追加 "a" 模式打开文件时,若文件不存在,fopen 返回 NULL。用 perror 打印系统提示。

c 复制代码
#include <stdio.h>

int main(void) {
    FILE *file = fopen("file.txt", "r");
    if (file == NULL) {
        perror("Error");
        return 1;
    }
    fclose(file);
    return 0;
}

输出:

Error: No such file or directory

2. 处理 "权限被拒绝"

文件存在但无权限时,fopen 同样返回 NULL,perror 会输出 "Permission denied"。

c 复制代码
FILE *file = fopen("/restricted/file.txt", "w");
if (file == NULL) {
    perror("Permission denied");
}

3. 处理 "磁盘已满"

写入后通过 ferror 检测流错误。

c 复制代码
#include <stdio.h>

int main(void) {
    FILE *fptr = fopen("file.txt", "w");
    if (fptr == NULL) {
        perror("Error opening file");
        return 1;
    }

    fprintf(fptr, "Writing to file");

    if (ferror(fptr)) {
        perror("Error writing to file");
    }
    fclose(fptr);
    return 0;
}

输出示例:

Error writing to file: Permission denied

4. 处理 "文件已存在"

用 "wx" 模式创建新文件;若文件已存在,fopen 返回 NULL 并置 errno 为 EEXIST。

c 复制代码
#include <stdio.h>
#include <errno.h>

int main(void) {
    FILE *fptr = fopen("test.text", "wx");
    if (fptr == NULL) {
        if (errno == EEXIST)
            printf("File already exist\n");
        return 1;
    }
    fprintf(fptr, "This is a new file.");
    fclose(fptr);
    return 0;
}

输出:

File already exist

5. 处理 "无效文件指针"

任何读写前都先判断指针是否为 NULL。

c 复制代码
FILE *file = NULL;
if (file == NULL) {
    printf("Invalid file pointer. File operations cannot proceed.\n");
}

6. 处理 "已到文件尾 (EOF)"

读取时用 feof 区分"正常读完"与"读取出错"。

c 复制代码
#include <stdio.h>

int main(void) {
    FILE *file = fopen("test.txt", "r");
    int ch;
    while ((ch = fgetc(file)) != EOF)
        putchar(ch);

    if (feof(file))
        printf("End of file reached.");
    else if (ferror(file))
        printf("Error reading the file.");
    fclose(file);
    return 0;
}

输出:

End of file reached.

7. 处理 "文件未打开"

fopen 返回 NULL 即表示打开失败,直接判断即可。

c 复制代码
#include <stdio.h>
int main(void) {
    FILE *file = fopen("example.txt", "r");
    if (file == NULL) {
        printf("File could not be opened.\n");
    } else {
        printf("File opened successfully.\n");
        fclose(file);
    }
    return 0;
}

输出:

File could not be opened.

8. 处理 "关闭文件失败"

fclose 返回 -1 表示关闭出错。

c 复制代码
#include <stdio.h>

int main(void) {
    FILE *fptr = fopen("test.txt", "w");
    fprintf(fptr, "Writing to file");

    if (fclose(fptr) == -1)
        printf("File closing error");
    else
        printf("File closed");
    return 0;
}

输出:

File closing error

相关推荐
煤球王子9 小时前
学而时习之:C语言中的Exception处理
c
BlackQid3 天前
深入理解指针Part3——指针与数组
c
要做朋鱼燕3 天前
【AES加密专题】1.AES的原理详解和加密过程
运维·网络·密码学·c·加密·aes·嵌入式工具
煤球王子4 天前
学而时习之:C语言中的Error处理
c
qq_437896438 天前
unsigned 是等于 unsigned int
开发语言·c++·算法·c
Lonble9 天前
C语言篇:预处理
c语言·c
BlackQid11 天前
深入理解指针Part1——C语言
c++·c
Lonble23 天前
C语言篇:宏
c语言·c
Lonble23 天前
C语言篇:翻译阶段
c语言·c