前言: 这篇文章是关于文件操作的下半篇,由于本章的篇幅较长,所以分两篇总结本章知识,这是文件操作上半篇的链接 http://t.csdn.cn/RkaMo
需要的小伙伴们可以去浏览一下喔,最后,感谢您的来访!
在讲这一章之前我想补充一些知识:
补充的知识点:>
标准流
标准流有三种:关于流的知识上一章有设计到,可以去看一下。
stdin - 标准输入流(standard input stream)
用于读取普通输入的流,在大多数环境中从键盘中为从键盘输入。scanf与getchar等函数会从这个流中读取字符。
stdout - 标准输出流(standard output stream)
用于写入普通输出的流,在大多数环境中为输出至显示器界面,printf、puts与putchar等函数会向这个流写入字符。
stderr - 标准错误流(standard error stream)
用于写出错误的流。在大多数环境中为输出至显示器界面。
FILE型
表示标准流的stdin、stdout、stderr都是指向FILE型的指针型。FILE型要在头文件<stdio.h>中定义,该数据类型用于记录控制流所需要的信息,其中包括以下数据
文件位置指示符(file position indicator)
记录当前访问地址。
错误指示符(error indicator)
记录是否发生了读取错误或写入错误。
文件结束指示符(EOF indicator)
记录是否已到达文件末尾。
通过流进行的输入输出都是根据上述信息执行操作的。而且这些信息也会随着操作结果更新。FILE 型的具体实现方法因编译器而异,一般多以结构体的形式实现。
fopen(打开文件)
大家在使用纸质笔记本时通常都是先打开,然后再翻页阅读或在适当的地方书写。
程序中的文件处理过程也同样如此。首先打开文件并定位到文件开头,然后找到要读取或写入的目标位置进行读写操作,最后将文件关闭。
打开文件的操作称为打开(open)。函数库中的fopen函数用于打开文件。
注意:使用文件时,需要事先用fopen函数打开文件。
该函数需要两个参数。第1个参数是要打开的文件名,第2个参数是文件类型及打开模式。以下图为例,使用"r”模式打开文件"abc.txt"。
- 文件类型有两种,即文本文件和二进制文件。接下来会讲到。
fopen函数会为要打开的文件新建一个流,然后返回一个指向FILE型对象的指针,该FILE型对象中保存了控制这个流所需要的信息。
文件一旦打开后,就可以通过FILE *型指针对流进行操作。
- 和程序启动时便准备好的标准流不同,要打开文件时必须先在程序中定义FILE * 型的指针变量。然后将fopen函数返回的指针赋于该变量,就可以通过该指针变量对文件进行操作了。
变量可以任意命名,这里我们将它命名为fp。fp不是流的实体,而是指向流的指针,严格来讲应称之为“指针fp所指向的流”。
fclose(关闭文件)
当我们读完一本书时会将它合上,文件也同样如此。在文件使用结束后,就要断开文件与流的关联将流关闭。这个操作就称为关闭(close)文件。
以下是用于关闭文件的fclose函数说明。
fclose
头文件 | #include<stdio.h> |
原型 | int fclose(FILE *stream); |
说明 | 刷新stream所指向的流,然后关闭与该流相关联的文件。流中留在缓冲区里面尚未写入的数据会被传递到宿主环境”,由宿主环境将这些数据写入文件。而缓冲区里面尚未读取的数据将被丢弃。然后断开流与文件的关联。如果存在系统自动分配的与该流相关联的缓冲区,则会释放该缓冲区。 |
返回值 | 若成功地关闭流,则返回0。检查到错误时返回EOF。 |
下图为关闭文件的示意图。只要将打开文件时fopen函数返回的指针传给fclose函数即可。
5.文件的随机读写💻
5.1 fwrite📂
fwrite用于函数的读取以下为说明:
fwrite
头文件 | #include<stdio.h> |
原型 | size_t fwrite (const void *ptr, size_t size,size_t nmemb,FILE *stream) ; |
说明 | 从ptr指向的数组中将最多nmemb个长度为size的元素写入stream指向的流中。若定义了流的文件位置指示符,则以成功写入的字符数为单位向前移动。当发生错误时,该流的文件位置指示符的值不可预测。 |
返回值 | 返回成功写入的元素个数。仅当发生写入错误时,元素个数会少于nmemb。 |
实例代码:二进制输出(二进制的写)
#include<stdio.h> //fwrite struct S { char name[20]; int age; float score; }; int main() { struct S s={"zhangsan",20,95.5f}; FILE* pf = fopen("test.aaa", "wb");//这个后缀.aaa可以任意命名 if (pf == NULL) { perror("fopen"); return 0; } fwrite(&s, sizeof(struct S), 1, pf); //关闭文件 fclose(pf); return 0; }
执行:以二进制的信息写进文本文件,记事本打开,我们肉眼看不懂,
5.2fread📂
fread
头文件 | #include<stdio.h> |
原型 | size_t fread (const void *ptr, size_t size,size_t nmemb,FILE *stream); |
说明 | 从stream指向的流中最多读取nmemb个长度为size的元素到ptr指向的数组。若定义了流的文件位置指示符,则以成功读取的字符数为单位向前移动。当发生错误时,该流的文件位置指示符的值不可预测。只读取到某一元素的部分内容时,值不可预测。 |
返回值 | 返回成功读取的元素个数。当发生读取错误或达到文件末尾时,元素个数会少于nmemb。 若size或nmemb为0,则返回0。这时数组内容和流的状态都不发生变化。 |
实例到代码::二进制输入 (二进制的读)
struct S { char name[20]; int age; float score; }; int main() { struct S s = { 0 }; FILE* pf = fopen("test.aaa","rb");//二进制的读 if (pf == NULL) { perror("fopen"); return 0; } //读文件 fread(&s, sizeof(struct S), 1, pf); printf("%s %d %f", s.name, s.age, s.score); //关闭文件 fclose(pf); pf = NULL; }
执行:
关于fwrite和fread:
这两个函数会接收4个参数。第一个参数是指向读写数据的首地址的指针,第二个参数是数据的长度,第三个参数是数据的个数,第四个参数是指向读写对象的流的指针。