是我们的程序哪里出错了吗?其实并不是,而是因为我们使用了" wb "方式,即以二进制形式进行了写入,所以我们在尝试直接查看时显示的是二进制符号。
所以我们就需要换一种方式才能对我们的文件内容进行查看。首先选中我们的“ 源文件 ”栏,右击选择“ 添加 ” -> “ 添加现有项 ”,将写入时创建的 txt 文件添加进来:
然后选中 txt 文件,右击选择“ 打开方式 ”选项:
接着在选项框中下拉选择“ 二进制编辑器 ”:
这时我们就看到了文件内的实际存储情况了:它显示我们的文件中的实际存储数据为 10 27 00 00,这又是怎么来的呢?这是因为,我们在存储时根据语句:
fwrite(&a, 4, 1, p);
根据这条语句,我们在进行数据写入时,是四个字节一组进行写入的,于是根据其二进制码可以得到它的存储为:
每四个字节进行划分: 0000 0000 0000 0000 0010 0111 0001 0000 于是得到: 00 00 27 10
又因为在之前我们就验证过我的计算机采用的是小端存储模式
,于是在进行压栈时会将数据进行倒置存储,于是就有:
10 27 00 00
5. 文件读取结束的判定:
5.1 错误使用 feof 函数:
- 在文件的读取过程中,不能通过 feof 函数的返回值来判定文件是否读取结束。
- 该函数的作用为,在已经确定文件读取结束的情况下,用于判定文件读取结束的原因。
5.2 判断文件读取结束:
如何正确判断文件是否读取结束?
文本文件判断文件读取结束方法:
①. 使用
fgetc
函数判断是否为EOF
。②. 使用
fgets
函数判断返回值是否为NULL
。
#include<stdio.h> #include<stdlib.h> 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; }
二进制文件判断文件读取结束方法:
使用
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; }
6. 文件缓冲区:
文件缓冲区是用以暂时存放读写期间的文件数据而在内存区预留的一定空间。通过磁盘缓存来实现,磁盘缓存不是一种实际存在的存储介质,它依托于固定磁盘,提供对主存储器存储空间的扩充,即利用主存中的存储空间, 来暂存从磁盘中读出 (或写入)的信息。
例如在国际 ANSI C 标准中,就是采用“ 缓冲文件系统 ”来对数据文件进行处理的。缓冲文件系统会自动地在我们的内存空间中为程序中的每个正在使用的文件开辟一块“ 文件缓冲区 ”。
计算机内存中向本地磁盘中输出数据:
将会先送至缓冲区->将缓冲区全部装满后->一并送达磁盘。
从磁盘向计算机读入数据:
从磁盘文件中读取数据->并将其输入至缓冲区->并在充满缓冲区后再逐个地将数据送达程序数据区
而至于缓冲区的大小,则是由 C 编译系统决定的
验证缓冲区:
#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 语言程序代码的编写过程中,在对文件进行操作时,需要刷新缓冲区并在文件操作结束时关闭文件,否则就可能导致文件的读写操作出现问题。
7.总结:
今天我们了解了文件操作与管理的相关知识,学习了文件的顺序读写、随机读写、文件读取结束的判定以及文件缓冲区的相关介绍,并且对文本文件和二进制文件有了一定的了解和区分,通过文件操作,可以实现对本地文件的修改与维护,希望我的文章和讲解能对大家的学习提供一些帮助。
当然,本文仍有许多不足之处,欢迎各位小伙伴们随时私信交流、批评指正!我们下期见~