【c语言进阶】文件操作(下)(二)

简介: 【c语言进阶】文件操作(下)(二)

三、文件结束的判定:


1.错误使用 feof 函数:


 在一段时间的交流中,我发现有很多小伙伴们都错误的使用了 feof 函数,将其用于判断文件是否读取结束 ,而这种使用方式是错误的。


我们应该记住:


在文件的读取过程中,不能通过 feof 函数的返回值来判定文件是否读取结束。

该函数的作用为:在已经确定文件读取结束的情况下,用于判定文件读取结束的原因


2.一些判断文件结束的总结:


2.1. 文本文件读取是否结束:


要判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )

例如:

fgetc 判断是否为 EOF .

fgets 判断返回值是否为 NULL .


int main()
{
    int c; 
    //注意:int,非char,要求处理EOF
    FILE* fp = fopen("test.txt", "r");
    if (!fp)
    {
        perror("File opening failed");
        return 1;
    }
    // fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF
    while ((c = fgetc(fp)) != EOF)
    // 标准C I/O读取文件循环
    {
        putchar(c);
    }
    //判断是什么原因结束的
    if (ferror(fp))
    {
        puts("I/O error when reading");
    }
    else if (feof(fp))
    {
        puts("End of file reached successfully");
    }
    fclose(fp);
    fp = NULL;
  return 0;
}



2.2. 二进制文件的读取结束判断,


判断返回值是否小于实际要读的个数。

例如:

fread判断返回值是否小于实际要读的个数。


#include<stdio.h>
enum {
    SIZE = 5
};
int main(void)
{
    double a[SIZE] = { 1.,2.,3.,4.,5. };
    FILE* fp = fopen("test.bin", "wb");
    //必须用二进制模式
    fwrite(a, sizeof * a, SIZE, fp);
    //写 double 的数组
    fclose(fp);
    double b[SIZE];
    fp = fopen("test.bin", "rb");
    size_t ret_code = fread(b, sizeof * b, SIZE, fp);
    //读 double 的数组
    //判断是否读取成功
    if (ret_code == SIZE)
    {
        puts("Array read successfully, contents: ");
        for (int n = 0; n < SIZE; ++n) printf("%f ", b[n]);
        putchar('\n');
    }
    //寻找读取失败的原因:
    else {
    // error handling
        if (feof(fp))
        {
            printf("Error reading test.bin: unexpected end of file\n");
        }
        else if (ferror(fp))
        {
            perror("Error reading test.bin");
        }
    }
    fclose(fp);
    fp = NULL;
    return 0;
}


3.判断原因的两个函数:


2f97fb6213359392aa1ac9db4c1be168_830e427b35a346618cac4c848e57a9e0.png


四、缓冲区的简单介绍


 文件缓冲区是用以暂时存放读写期间的文件数据而在内存区预留的一定空间。

 ANSIC 标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”.从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。


1eb8f85383b3ad89d8d93ba468d10189_5590d6f671ca4a8ba2f7bdc5fec5788a.png


 要使缓冲区的内容进入内存或者计算机硬盘有两种方法,第一种是缓冲区充满自动填入,第二个是主动刷新缓冲区。


64c0e5e247083e0d46b44b23eddebb33_0828773f0a9c4bec947ce8db480487a2.png


举个例子:


#include <stdio.h>
#include <Windows.h>
//VS2022 WIN10环境测试
int main()
{
  FILE* pf = fopen("test.txt", "w");
  fputs("abcdef", pf);
  //先将代码放在输出缓冲区
  printf("睡眠10秒\n");
  //已经写数据了,但是打开test.txt文件,发现文件没有内容
  Sleep(10000);
  printf("刷新缓冲区\n");
  fflush(pf);
  //刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘)
  //注:fflush 在高版本的VS上不能使用了
  printf("再睡眠10秒\n");
  //此时,再次打开test.txt文件,文件有内容了
  Sleep(10000);
  fclose(pf);
  //注:fclose在关闭文件的时候,也会刷新缓冲区
  pf = NULL;
  return 0;
}


 所以在这里,各位小伙伴们一定要注意了,因为缓冲区的存在,数据只有在填满缓冲区后才会进行真正的写入或读取,所以在 C 语言程序代码的编写过程中,我们一定要在文件操作结束时关闭文件,否则就可能导致文件的读写操作出现问题。


总结:


 经过今天内容的补充,我们关于文件操作与管理的知识就全部学完了,不知道小伙伴们是否掌握了呢?

 更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

目录
相关文章
|
18小时前
|
存储 程序员 C语言
C语言之详细讲解文件操作(抓住文件操作的奥秘)
C语言之详细讲解文件操作(抓住文件操作的奥秘)
6 0
|
2天前
|
存储 程序员 C语言
C语言:文件操作
C语言:文件操作
11 1
|
2天前
|
存储 C语言 C++
【C语言】文件与文件操作
前言:我们通过学习的技术可以完成计算与字符串处理,但程序结束之后就都消失了,这样岂不可惜。我们通过文件与数据持久化保存相关的基础知识。
10 0
|
2天前
|
存储 编译器 C语言
C语言中的文件操作指南
C语言中的文件操作指南
14 0
|
2天前
|
算法 C语言
【C 言专栏】C 语言文件操作的技巧与方法
【4月更文挑战第30天】本文介绍了C语言文件操作的关键技巧,包括文件的打开与关闭(使用`fopen`和`fclose`函数),读取(`fgetc`、`fgets`和`fread`)和写入(`fputc`、`fputs`和`fwrite`)操作。此外,还讨论了文件指针移动(`fseek`)、错误处理、文件权限和格式等问题。文中提供了一个简单的读写文件的示例,并提到了高级技巧如随机访问、文件缓冲和截断。掌握这些技能将有助于提升C语言编程中的文件处理能力。
|
2天前
|
存储 C语言
C语言进阶---------作业复习
C语言进阶---------作业复习
|
2天前
|
存储 Linux C语言
C语言进阶第十一节 --------程序环境和预处理(包含宏的解释)-2
C语言进阶第十一节 --------程序环境和预处理(包含宏的解释)
|
2天前
|
自然语言处理 Linux 编译器
C语言进阶第十一节 --------程序环境和预处理(包含宏的解释)-1
C语言进阶第十一节 --------程序环境和预处理(包含宏的解释)
|
2天前
|
存储 C语言
C语言进阶第十课 --------文件的操作-2
C语言进阶第十课 --------文件的操作
|
2天前
|
存储 编译器 C语言
C语言进阶第十课 --------文件的操作-1
C语言进阶第十课 --------文件的操作