✨四、文件操作
⛲1.文件的打开和关闭
文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。
在编写程序的时候,在打开文件的同时,都会返回一个FILE* 的指针变量指向该文件,也相当于建立了
指针和文件的关系。
ANSIC规定使用fopen函数来打开文件,fclose来关闭文件。
①fopen(打开)
函数原型:FILE* fopen(const char* filename, const char* mode);
函数功能:Open a file.(打开文件)
返回类型:Each of these functions returns a pointer to the open
file.A null pointer value indicates an error.(如果打开成功,返回指向文件信息区的指针,如果返回失败,返回空指针NULL)
函数参数1:filename(文件名,实际上包括3部分内容,而不仅仅是文件名主干。如果文件路径未写,则默认本路径)
函数参数2:Type of access permitted(文件打开方式)
文件打开方式如下表:
注意:‘w’打开的时候如果有同名文件,该文件中的内容会被销毁
②fclose(关闭)
函数原型:int fclose(FILE* stream);
函数功能:Closes a stream(fclose) or closes all open streams(_fcloseall).(关闭文件)
返回类型:fclose returns 0 if the stream is successfully closed._fcloseall returns the total number of streams closed.Both functions return EOF to indicate an error(关闭文件成功返回0,关闭文件失败返回EOF(值为 - 1)来报错)
函数参数:Pointer to FILE structure(文件指针)
举例:
1)在项目工程所在文件路径下新建一个测试文件
2)测试代码
3)文件打开结果
调整一下(为了进一步理解相对路径和绝对路径,这里的filename使用绝对路径的方式)
刚刚我们是以“读”的方式来打开文件,现在我们来尝试用“写”的方式来打开文件
在我们刚刚的路径下是没有file1.dat这个文件的,因为我们用“w”的方式打开文件,所以会创建一个新的文件
⛳2.文件的顺序读写
①fputc函数 与 fgetc函数
(1)举例 :fput写入字符
写入成功
(2)举例 :fgetc写入字符
成功输出
②流(stream)的概念
输入输出是数据传送的过程, 数据如流水一样从一处流向另一处, 因此常将输入输出形象地称为流(stream), 即数据流。
流表示了信息从源到目的端的流动。在输入操作时, 数据从文件流向计算机内存, 在输出操作时, 数据从计算机流向文件(如打印机、磁盘文件)。文件是由操作系统进行统一管理的, 无论是用Word打开或保存文件, 还是C程序中的输入输出都是通过操作系统进行的。“流”是一个传输通道, 数据可以从运行环境(有关设备)流入程序中, 或从程序流至运行环境。
C语言把文件看作一个字符(或字节)的序列, 即由一个一个字符(或字节)的数据顺序组成。一个输入输出流就是一个字符流或字节(内容为二进制数据)流。
C的数据文件由一连串的字符(或字节)组成, 而不考虑行的界限, 两行数据间不会自动加分隔符,对文件的存取是以字符(字节)为单位的。输入输出数据流的开始和结束仅受程序控制而不受物理符号(如回车换行符)控制, 这就增加了处理的灵活性。
这种文件称为流式文件。
*C语言程序,只要运行起来,就默认打开了三个流,类型均为FILE
stdin-- - 标准输入流-- - 键盘 stdout-- - 标准输出流-- - 屏幕 stderr-- - 标准错误流-- - 屏幕
知道这个概念有个想法,他就可以从键盘上输入然后屏幕读出来
看下面代码例子:
接下来我们进行读文件,将生成的文件读出来
刚刚这种是从文件里面读,我们也可以从标准输入流stdin–键盘读
上面说的fputc\fgetc都是一个个字符方式读取的,如果要用这两个函数来处理字符串的话,效率就会非常低,那么用没用类似于这两个函数,但是可以一行一行读取的函数呢?
③fgets(读取) 与 fputs(写入)函数
这两个函数就是用来实现刚刚说的功能的。
举例fgets :
1)我们在文档中输入
2)我们使用fgets读取文件信息
举例二 :fputs输入数据到文件中
1)使用fputs输入 HELLO WORLD
2 )文本里面内容被修改
注意:
如果想要写入的字符串换行,则需要在字符串内容中添加换行‘\n’
举例3 : 从键盘上读取一行文本
④fscanf(读取)与fprintf(写入)函数
**前面进行的是字符的输入输出, 而实际上数据的类型是丰富的。**大家已很熟悉用printf 函数和scanf 函数向终端进行格式化的输入输出, 即用各种不同的格式以终端为对象输入输出数据。其实也可以对文件进行格式化输入输出, 这时就要用fprintf函数和 fscanf函数, 从函数名可以看到, 它们只是在printf和 scanf的前面加了一个字母f。它们的作用与printf 函数和scanf函数相仿, 都是格式化读写函数。
只有一点不同: fprintf 和 fscanf 函数的读写对象不是终端而是文件。
**它们的一般调用方式为 : **
fprintf(文件指针, 格式字符串, 输出表列);
fscanf(文件指针, 格式字符串, 输入表列);
函数格式就是这样
就比printf前面多了一个流
1)举例1 :fprintf函数写数据到文件里
结果展示:
2)举例2:fscanf(读取)函数得到文件数据
现在我们将输出的结构体文件重新读入到结构体变量中:
当然我们也可以用fprintf,stdout是标准输出流,也就是屏幕
上面我们说谈到的输入和输出实际上都是以文本数据的形式,也就是ASCII码形式。
⑤fread(二进制输出) 与fwrite(二进制输出)
在程序中不仅需要一次输入输出一个数据, 而且常常需要一次输入输出一组数据(如数组或结构体变量的值),C语言允许用fread函数从文件中读一个数据块, 用fwrite函数向文件写一个数据块。在读写时是以二进制形式进行的。在向磁盘写数据时, 直接将内存中一组数据原封不动、不加转换地复制到磁盘文件上, 在读入时也是将磁盘文件中若干字节的内容一批读入内存。
函数原型 :
注意:
1)
buffer:是一个地址
。 对fread来说, 它是用来存放从文件读入的数据的存储区的地址。 对fwrite来说,是要把此地址开始的存储区中的数据向文件输出(以上指的是起始地址)。2)
size : 要读写的字节数
。3)
count : 要读写多少个数据项(每个数据项长度为size)
。4)
fp : FILE类型指针
。 在打开文件时指定用二进制文件, 这样就可以用fread和 fwrite函数读写任何类型的信息。
举例(一) :fwrite函数写入二进制数据进文件中
结果展示:
举例(二) :fread函数读取文件中的二进制,并打印
⑥对比一组函数
scanf / fscanf / sscanf
printf / fprintf / sprintf
scanf与printf是一组-- - 从标准输入流(stdin) / 输出流(stdout)中输入 / 输出格式化的数据
fscanf与fprintf一组-- - 从所有流类型(包括标准输入流\输出流,文件流等各种流)输入 / 输出格式化的数据
sscanf与sprintf一组-- - 从一个字符串中输入 / 输出格式化数据
函数原型
sscanf 与 sprintf 使用举例:
⚽3.文件随机读取
一般情况下, 在对字符文件进行顺序读写时, 文件位置标记指向文件开头, 这时如果对文件进行读的操作, 就读第1个字符, 然后文件位置标记向后移一个位置, 在下一次执行读的操作时, 就将位置标记指向的第⒉个字符读入。依此类推, 遇到文件尾结束。
可以根据读写的需要, 人为地移动文件位置标记的位置。文件位置标记可以向前移、向后移, 移到文件头或文件尾, 然后对该位置进行读写,
显然这就不是顺序读写了, 而是随机读写。
①fseek函数
根据文件指针的位置和偏移量来定位文件指针。
函数原型:
起始点的选项有三个
举例:
1)准备文件,输入一串字符
2)使用 fseek函数
3)运行结果
现在我们运用fseek函数对当前文件指针位置进行偏移,
比如:
本来pf读了a之后,应该移动到b的位置,但是用fseek让其偏移 - 1,也就是向左偏移一个位置(一个字节),又回到了a。
当起始点为SEEK_END 的时候,只能向左(向前)偏移,也就是偏移量只能为负值
当起始点为SEEK_SET 的时候,只能向右(向后)偏移,也就是偏移量只能为正值
②ftell函数
返回文件指针相对于起始位置的偏移量
函数原型:
举例:
③rewind函数
让文件指针的位置回到文件的起始位置
函数原型:
举例 ;
结果展示:
⌚4.文件结束判定
①feof函数
常被被错误使用的
feof函数
牢记 : 在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束。而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。
- 文本文件读取是否结束,判断返回值是否为EOF (fgetc),或者NULL(fgets)
例如:fgetc判断是否为EOF. fgets判断返回值是否为NULL.
- 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
例如:fread判断返回值是否小于实际要读的个数
例如∶
1.fread判断返回值是否小于实际要读的个数。 fgetc函数在读取结束的时候,会返回EOF 正常读取的时候,返回的是字符的AscII码值
2.fgets函数在读取结束的时候,会返回NULL 正常读取的是时候,返回存放字符串的空间起始地址。
3.fread函数在读取的时候,返回的是实际读取到的完整元素的个数,如果发现读取到的完整元素的个数小于实际要读取(指定要读取)的个数,这就是最后一次读取了。
举例:
(1)先创建一个test.txt文件,然后在里面随便编辑点内容进行保存
2)编写代码,将刚刚test.txt文件的内容读出来放到一个新文件test2.txt当中(相当于复制拷贝一份test.txt)
程序运行后,在源文件路径下生成test2.txt
打开test.txt和test2.txt进行对比,会发现两者是一样的
代码举例:文本文件
代码举例:二进制文件