要将数据进⾏持久化的保存,我们可以使用文件。
磁盘(硬盘)上的⽂件是⽂件。
我们⼀般谈的⽂件有两种:程序⽂件、数据⽂件(从⽂件功能的⻆度来分类。
程序⽂件包括源程序⽂件(后缀为.c),⽬标⽂件(windows环境后缀为.obj),可执⾏程序(windows环境后缀为.exe)。
数据文件:⽂件的内容不⼀定是程序,⽽是程序运⾏时读写的数据,⽐如程序运⾏需要从中读取数据的⽂件,或者输出内容的⽂件。有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使⽤,这⾥处理的就是磁盘上⽂件。
⽂件名包含3部分:⽂件路径+⽂件名主⼲+⽂件后缀
例如: c:\code\test.txt 为了⽅便起⻅,⽂件标识常被称为⽂件名
数据⽂件被称为⽂本⽂件或者⼆进制⽂件
数据在内存中以⼆进制的形式存储,如果不加转换的输出到外存的⽂件中,就是⼆进制⽂件。
如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的⽂件就是⽂本⽂件。
10000的二进制序列就是 内存中:0000 0000 0000 0000 0010 0111 0001 0000。
以二进制的形式直接存储,这样的形式被称为二进制文件。
以小端存储,他的形式就是0001 0000 0010 0111 0000 0000 0000 0000
翻译为二进制文本文件就是 102700,如果我们要打开二进制文本文件,步骤如下:右击源文件,点击打开方式,点击二进制编辑器,点击确定。
如果以ASCII码的形式输出到磁盘,则磁盘中占⽤5个字节(每个字符⼀个字节),⽽
⼆进制形式输出,则在磁盘上只占4个字节(VS2019测试)。
文件的打开和关闭
C程序针对⽂件、画⾯、键盘等的数据输⼊输出操作都是通过流操作的。
⼀般情况下,我们要想向流⾥写数据,或者从流中读取数据,都是要打开流,然后操作。
那为什么我们从键盘输⼊数据,向屏幕上输出数据,并没有打开流呢?
那是因为C语⾔程序在启动的时候,默认打开了3个流:
• stdin 标准输⼊流,在⼤多数的环境中从键盘输⼊,scanf函数就是从标准输⼊流中读取数据。
• stdout 标准输出流,⼤多数的环境中输出⾄显⽰器界⾯,printf函数就是将信息输出到标准输出
流中。
• stderr 标准错误流,⼤多数环境中输出到显⽰器界⾯。
stdin、stdout、stderr三个流的类型是: FILE* ,通常称为⽂件指针。
C语⾔中,就是通过 FILE* 的⽂件指针来维护流的各种操作的。默认打开了这三个流,我们使⽤scanf、printf等函数就可以直接进⾏输⼊输出操作的。
每个被使⽤的⽂件都在内存中开辟了⼀个相应的⽂件信息区,⽤来存放⽂件的相关信息(如⽂件的名字,⽂件状态及⽂件当前的位置等)。这些信息是保存在⼀个结构体变量中的。该结构体类型是由系统声明的,取名FILE。
通过⽂件指针变量能够间接找到与它关联的⽂件。
文件的打开和关闭
在打开⽂件的同时,都会返回⼀个FILE*的指针变量指向该⽂件,也相当于建⽴了指针和⽂件的关系。
/打开⽂件 FILE * fopen ( const char * filename, const char * mode ); //关闭⽂件 int fclose ( FILE * stream );
mode表⽰⽂件的打开模式
w写数据,会把原有数据清空
文件的顺序读写
所有输⼊流⼀般指适⽤于标准输⼊流和其他输⼊流(如⽂件输⼊流);所有输出流⼀
般指适⽤于标准输出流和其他输出流(如⽂件输出流)。
对⽐⼀组函数:
scanf/fscanf/sscanf
scanf 从标准输入流上读取格式化的数据
fscanf 从指定输入流上读取格式化的数据
sscanf
printf/fprintf/sprintf
把数据以格式化的形式打印在标准输出流上
与printf相比,多了一个文件流的参数。
把数据以格式化的形式打印在指定输出流上
把格式化的数据转换成字符串
文件的随机读写
fseek
根据⽂件指针的位置和偏移量来定位⽂件指针。
如图,从当前位置偏移4个位置
rewind
void rewind ( FILE * stream );
让⽂件指针的位置回到⽂件的起始位置
int main () { int n; FILE * pFile; char buffer [27]; pFile = fopen ("myfile.txt","w+"); for ( n='A' ; n<='Z' ; n++) fputc ( n, pFile); rewind (pFile); fread (buffer,1,26,pFile); fclose (pFile); buffer[26]='\0'; printf(buffer); return 0; }
retell
返回文件指针相对于起始位置的偏移量
long int ftell ( FILE * stream );
文件读取结束的判定
在⽂件读取过程中,不能⽤feof函数的返回值直接来判断⽂件的是否结束。
feof 的作⽤是:当⽂件读取结束的时候,判断是读取结束的原因是否是:遇到⽂件尾结束。
⽂本⽂件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )
例如:
• fgetc 判断是否为 EOF
• fgets 判断返回值是否为 NULL
. ⼆进制⽂件的读取结束判断,判断返回值是否⼩于实际要读的个数。
fread
fclose也会将缓冲区刷新,所以在启用fclose之前,先睡眠10秒钟。
如果从磁盘向计算机读⼊数据,则从磁盘⽂件中读取数据输
⼊到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小是由编译系统决定的。