初出茅庐的小李博客之C语言文件操作

C语言文件操作

在C语言中,文件操作主要是通过标准库函数来实现的。

今天有时间就来学习下一些常用的文件操作函数:

C 语言提供了一个 FILE 数据结构,记录了操作一个文件所需要的信息。该结构定义在头文件stdio.h,所有文件操作函数都要通过这个数据结构,获取文件信息。

struct _iobuf 
{
    char *_ptr;      // 指向缓冲区当前位置的指针
    int _cnt;        // 缓冲区中剩余的字节数
    char *_base;     // 指向缓冲区起始位置的指针
    int _flag;       // 文件状态标志(如错误、文件结束等)
    int _file;       // 文件描述符或句柄
    int _charbuf;    // 用于单字符缓冲
    int _bufsiz;     // 缓冲区大小
    char *_tmpfname; // 临时文件名指针(如果有)
};
typedef struct _iobuf FILE;  // 将结构体重命名为 FILE 类型

什么是文件指针:

开始操作一个文件之前,就要定义一个指向该文件的 FILE 指针,相当于获取一块内存区域,用来保存文件信息。

定义方式:

FILE* fp;

fopen()函数用来打开文件。所有文件操作的第一步,都是使用fopen()打开指定文件。这个函数的原型定义在头文件stdio.h

FILE* fopen(char* filename, char* mode);

它接受两个参数。第一个参数是文件名(可以包含路径),第二个参数是模式字符串,指定对文件执行的操作,比如下面的例子中,r表示以读取模式打开文件;

第一次运行如果没有这个文件,程序会提示错误。如下所示,所以要想以只读的形式打开这个文件那么这样文件要事先存在。我在桌面手动创建了这个文件。再次试验就可以成果打开。

第一次打开出错:
在这里插入图片描述

第二次打开正常:
在这里插入图片描述

打开文件之后我们试着用fread()来读取文件信息。

fread()函数用于一次性从文件读取较大的数据块,主要用途是将文件内容读入一个数组,适合读取二进制数据。它的原型定义在头文件stdio.h

size_t fread(void* ptr, size_t size,size_t nmemb,FILE* fp);

它接受四个参数

  • ptr:数组地址。
  • size:每个数组成员的大小,单位为字节。
  • nmemb:数组的成员数量。
  • fp:文件指针。

读取字节数可以用一个变量来接收,

// 从文件中读取数据
BytesRead = fread(buffer, sizeof(char), sizeof(buffer) - 1, fp);
printf("读到字节数BytesRead = %d\r\n",BytesRead);

在这里插入图片描述

读取数据时候有可能遇到文件为空的情况,这时候就需要检查是不是文件末尾。检查是否到文件末尾函数是feof

feof 是 C 标准库中的一个函数,用于检查文件是否已到达文件末尾(EOF,End of File)。它通常与文件读写函数(如 freadfgets 等)一起使用,以便在读取文件时检测到文件末尾。

feof 函数原型

int feof(FILE *stream);

参数解释

  • stream:指向 FILE 结构的文件指针。

返回值

  • 如果文件指针已到达文件末尾,则返回非零值 (真)。
  • 否则,返回零 (假)。

如果文本文件里面的内容是空的、那么读取到的数据字节数据应该是0。如图所示。

在这里插入图片描述

现在我试着网文件里写入一些信息。再尝试去读取信息

写入的信息是

This is a test txt.
Hello world!
end

编写读取数据到buffer的代码

    BytesRead = fread(buffer, sizeof(char), sizeof(buffer) - 1, fp);
    printf("读到字节数BytesRead = %d\r\n",BytesRead);
    if (BytesRead == 0)
     {
        if (feof(fp))//文件到达末尾返回非零的真值 
        {
            printf("空文件、到达文件末尾\n");
        }
        else if (ferror(fp))
        {
            perror("没读到数据、读取文件时出错");
        }
        fclose(fp);
        return -1;
    }
    buffer[BytesRead] = '\0';
    printf("文件内容: %s\n", buffer);

读取信息入下所示:

打开文件时正常: No error
读到字节数BytesRead = 36
文件内容:
This is a test txt.
Hello world!
end
--------------------------------
Process exited after 0.04219 seconds with return value 0
请按任意键继续. . .

在这里插入图片描述

fclose 是 C 标准库中的一个函数,用于关闭已经打开的文件。关闭文件可以释放与该文件相关的资源,并确保所有缓冲区中的数据被写入文件。

fclose 函数原型

int fclose(FILE *stream);

参数解释

  • stream:指向 FILE 结构的文件指针,该文件指针指向要关闭的文件。

返回值

  • 如果成功关闭文件,返回0。
  • 如果发生错误,返回 EOF(通常为 -1)

完整的代码如下:

#include <stdio.h>

int main(void)
{
    FILE *fp;         // 定义一个 FILE 类型的指针
    char buffer[256]; // 定义一个缓冲区用于存储读取的数据
    size_t BytesRead; // 定义读取到多少个字节

    // 打开一个文件用于读取
    fp = fopen("example.txt", "r");
    if (fp == NULL)
    {
        perror("打开文件时出错");
        return -1;
    }
    else
    {
        printf("打开文件正常\r\n");
    }

    // 从文件中读取数据
    BytesRead = fread(buffer, sizeof(char), sizeof(buffer) - 1, fp);
    printf("读到字节数 BytesRead = %zu\r\n", BytesRead);

    if (BytesRead == 0)
    {
        if (feof(fp)) // 文件到达末尾返回非零的真值
        {
            printf("空文件或到达文件末尾\r\n");
        }
        else if (ferror(fp))
        {
            perror("没读到数据,读取文件时出错");
        }
        fclose(fp);
        return -1;
    }

    // 为缓冲区添加字符串结束符
    buffer[BytesRead] = '\0';
    printf("文件内容:\r\n%s\r\n", buffer);

    // 关闭文件
    if (fclose(fp) == 0) // fclose 关闭成功返回0,关闭失败返回EOF
    {
        printf("成功关闭文件\r\n");
    }
    else
    {
        perror("关闭文件时出错");
    }

    return 0;
}

补充说明:EOF

C 语言的文件操作函数的设计是,如果遇到文件结尾,就返回一个特殊值。程序接收到这个特殊值,就知道已经到达文件结尾了。

头文件stdio.h为这个特殊值定义了一个宏EOF(end of file 的缩写),它的值一般是-1。这是因为从文件读取的二进制值,不管作为无符号数字解释,还是作为 ASCII 码解释,都不可能是负值,所以可以很安全地返回-1,不会跟文件本身的数据相冲突。

需要注意的是,不像字符串结尾真的存储了\0这个值,EOF并不存储在文件结尾,文件中并不存在这个值,完全是文件操作函数发现到达了文件结尾,而返回这个值。

fopen打开文件模式可能情况

以下是 fopen 函数的所有可能模式及其详细解释,包括注意事项:

模式模式说明文件指针位置文件存在文件不存在读操作写操作注意事项
r读模式文件开始读取文件返回 NULL允许不允许文件必须存在,否则返回 NULL。
w写模式文件开始文件内容被清空创建新文件不允许允许打开时会清空文件内容。
a追加写模式文件末尾文件末尾追加创建新文件不允许允许写操作总是在文件末尾。
r+读写模式文件开始读取和写入返回 NULL允许允许文件必须存在,否则返回 NULL。
w+读写模式文件开始文件内容被清空创建新文件允许允许打开时会清空文件内容。
a+读写模式文件末尾读取和追加创建新文件允许允许写操作总是在文件末尾。

注意事项

  1. r 模式

    • 只读模式,如果文件不存在,返回 NULL。因此在打开文件后,必须检查文件指针是否为 NULL
  2. w 模式

    • 只写模式,打开文件时会清空文件内容。如果文件不存在,则创建新文件。这种模式不允许读取文件内容。
  3. a 模式

    • 追加写模式,文件指针总是指向文件末尾。即使使用 fseek 移动文件指针,写入操作仍会在文件末尾。如果文件不存在,则创建新文件。这种模式不允许读取文件内容。
  4. r+ 模式

    • 读写模式,文件指针指向文件开始,允许读取和写入。如果文件不存在,返回 NULL。因此在打开文件后,必须检查文件指针是否为 NULL
  5. w+ 模式

    • 读写模式,打开文件时会清空文件内容,文件指针指向文件开始。如果文件不存在,则创建新文件。这种模式允许读取和写入,但注意文件内容会被清空。
  6. a+ 模式

    • 读写模式,文件指针指向文件末尾,允许读取和追加。如果文件不存在,则创建新文件。尽管可以读取文件内容,但写操作总是在文件末尾。

示例代码

以下是如何使用这些模式打开文件的示例代码:

#include <stdio.h>

void open_file(const char *filename, const char *mode) 
{
    FILE *fp = fopen(filename, mode);
    if (fp == NULL) 
    {
        perror("打开文件失败");
        return;
    }
    printf("以模式 '%s' 成功打开文件\r\n", mode);
    // 关闭文件
    if (fclose(fp) == 0) // fclose 关闭成功返回0,关闭失败返回EOF
    {
        printf("成功关闭文件\r\n");
    }
    else
    {
        perror("关闭文件时出错");
    }
}

int main(void) 
{
    open_file("example_r.txt", "r");
    open_file("example_w.txt", "w");
    open_file("example_a.txt", "a");
    open_file("example_r+.txt", "r+");
    open_file("example_w+.txt", "w+");
    open_file("example_a+.txt", "a+");
    return 0;
}

上边代码运行后只会产生四个文件

在这里插入图片描述

在这里插入图片描述

有关文件操作的接口还有以下几个,如果大家感兴趣可以点个在看,我继续更新!

fwrite():写入文件

fseek():移动文件指针到指定位置

ftell():获取文件指针当前位置

fgetc():从文件中读取一个字符

fputc():写入一个字符到文件中

fscanf():从文件中读取格式化输入

fprintf():按格式写入到文件中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值