C语言进阶指南(20)——文件操作

发布时间:2024年01月12日

欢迎来到博主的专栏:C语言进阶指南

一、流

流(scream)是一个抽象出来的概念,表示一个输入的源,或者输出的目的地。

比如前面常常用的scanf函数,就是从输入流(键盘输入的字符)向程序输入数据。printf函数就是通过输出流,向屏幕输出数据。

对文件进行读/写操作时,也需要打开一个流,通过这个流来输入/输出数据

二、 文件

打开电脑中的存储信息,这些存储在硬盘的被称为文件。文件有程序文件,数据文件
在这里插入图片描述

程序文件,用来存储程序(.exe)或者程序的源码(比如.c文件)的文件
数据文件,存储用来读/写的数据的文件称为数据文件

文件操作函数对象通常是数据文件,因此本篇文章中文件指的通常是数据文件

三、数据文件

数据文件根据数据存储的形式又分为二进制文件和文本文件

二进制文件

将数据以二进制的形式存储的文件被称为二进制文件。
比如将一个int类型的数据10000以二进制的形式存储在文件当中,那么数据在二进制中被记录为
在这里插入图片描述
考虑到vs编译器数据在内存中的存储形式是小端存储,所以实际的二进制存储形式应为

16 27 00 00(16进制)

文本文件

数据以ASCII码的形式存储在文件当中,这种文件被称为文本文件
以整型数据10000为例,文本文件的存储形式为数据的ASCII码形式。
在这里插入图片描述

四、流的打开方式

数据的输入\输出

在日常当中,计算机与外部设备是经常出现数据传递的,比如键鼠对计算机的操作、计算机向音箱传递数字信号等,这些都是计算机与外部设备的数据交换。

通常来说,完成这些操作都需要有硬件设备来进行连接,这些接口往往要进行硬件层面的操作,来实现这些功能。以图为例
在这里插入图片描述
作为更擅长于软件操作的程序员来说,程序员更需要考虑的是这些数据的处理、不用过多的考虑怎么将这些数据输出\输入到硬件设施。

流(scream)就能很好的做到这一点,流是一个承载这些数据的抽象概念。?便程序员对各种设备进??便的操作。如果需要对某些数据进行输入\输出的操作,只需要对“流”进行操作。

至于“流”与外部设备如何连接、传输,这是更加底层的原理、交由负责这一领域的工作者完成。程序员要做到的是对流进行操作。

“流”可以视为数据与外部设备的数据中转站,因为“流”是一大堆数据的抽象,可以视为是一片数据构成的数据地带。

在这里插入图片描述

文件流

文件里的数据可以通过流,传输给计算机。也可以让计算机通过流,传输给文件。 因此文件和计算机之间的流称为“文件流”。

文件指针

先来观看一个文件指针是如何创建的

FILE* PF;

可以看到这个指针的类型是很陌生的,不同于以往常见的数据类型(比如int,char,float……)。

这个FILE类型的变量不是C语言中原有的变量,而是一个定义在<stdio.h>这个头文件中,数据的主要内容是文件的信息。

每个文件在打开时都会在内存中开辟一个”文件信息区”。在这个信息区中,存储的内容都是文件的信息、如文件名、文件状态、文件位置等。

而这些数据的类型则是FILE类型,FILE类型可以在头文件中看到定义(不同的编译器有着不同的定义)

比如vs中的FILE类型的定义为
在这里插入图片描述
可以看到一个文件的信息、全都保存在这个结构体类型的数据当中。

在这里插入图片描述
这个文件信息的数据类型就是FILE类型。

用来指向这片文件信息区的指针,就叫做文件指针,类型为FILE*。

打开文件流

打开文件流用到一个打开文件的函数——fopen函数
在这里插入图片描述

(a)文件名

首先观察fopen的函数原型的第一个参数

filename是一个char*类型的指针,可以认为是一个字符串,这个字符串的含义是想要打开的文件“流”的文件名

文件名有两种形式
(1)相对路径
,即这个文件在磁盘中,相对于想要使用文件“流”的程序文件的相对的目录。

比如一个程序文件“test.c”为例,要在这个文件中打开一个“data.txt”的文本文件。可以翻找磁盘中“data.txt”的路径,相对路径的文件名遵循以下规则(“test.c”为当前文件,“data.txt”为目的文件)

.\表示当前文件的目录。
. .\表示当前文件的上一级目录。
如果目的文件在当前文件的上一级目录下再上一级,就在开头多加上. .\,以此类推。(注意\之前的小数点!!!!)
如果目的文件和当前文件一个目录,那么可以省略“.\”。

以下图为例。
在这里插入图片描述
“data.txt”与“test.c”在同一目录下,于是“data.txt”与“test.c”的相对路径为“.\data.txt”或者“data.txt”。
注意这个相对路径要以字符串的形式写进去,为了避免“\”生成转义字符,所以正确的写法应为

FILE* pf=fopen("data.txt", );

或者

FILE* pf=fopen(".\\data.txt",);

如果“data.txt”在“test,c”的上一级目录。
那么写法应为

	FILE* pf=fopen("..\\.\\data.txt", "w");

以此类推。
在这里插入图片描述
在这里插入图片描述

可以看到"data.txt"与“test.c”的相对路径是上一个目录的。
(2)绝对路径
可以通过查看文件的属性找到该文件的位置,然后复制粘贴下文件的所有级别的目录。

在这里插入图片描述
比如“data.txt”的绝对路径则是D:\code\test-c\test_1.4\data.txt(不知道为什么我的复制粘贴只能到当前目录–+,没事手动加上)
要注意避免老问题,即转义字符的问题。那么代码应写成

	FILE* pf=fopen("D:\\code\\test-c\\test_1.4\\data.txt",);

绝对路径的弊端在于,当程序移植到其他平台时,由于不同计算机的目录命名不同,移植性会大打折扣(通俗来说就是又要加班改代码啦!!!)所以建议使用相对路径来编写文件操作的

(b)打开模式

在这里插入图片描述
fopen函数的函数原型的第二个参数是“mode”

“mode”是一个char*类型的指针,可以当做一个字符串 “mode”是特定的字符串,用来决定文件的打开形式

以“data.txt”为例,如果想要以“只读”的形式打开,那么mode就是“r”。

	FILE* pf=fopen("data.txt", "r");

不同的打开模式,决定了程序员对该文件的操作权限,比如“只读”模式下,就只能从“data.txt”文件中读入数据,而不能向该文件写入数据。
在这里插入图片描述

(c)实际应用

fopen函数在输入了正确的参数时,会在文件信息区创建出该文件的文件信息,并返回一个FILE类型的指针来指向这片区域,所以通常用一个FILE类型的指针来接收该函数的返回值

FILE* pf=fopen("data.txt", "w");

若文件打开失败,则函数的返回值为NULL。所以可以对指针pf进行检测。

FILE* pf=fopen("data.txt", "w");
if (pf == NULL)
{
	exit(EXIT_FAILURE);
}

此时pf可以当做是这个文件与计算机之间的“流”了,后续对“流”的操作,都是使用文件对应的文件指针来操作。

(b)关闭文件流

在这里插入图片描述
文件流的关闭则显得比较简单了。

参数是一个file*类型的指针,这个指针指向先前打开的文件流

比如关闭“data.txt”的文件“流”,将pf作为参数传输进去即可

FILE* pf=fopen("data.txt", "w");
if (pf == NULL)
{
	exit(EXIT_FAILURE);
}
fclose(pf);

文件关闭函数顺利关闭文件流,则返回值为0。
如果文件关闭函数发生错误,返回值为EOF。
所以可以对fclose函数进行检测,来判断文件流关闭是否存在异常。

文章来源:https://blog.csdn.net/2301_77239666/article/details/135414921
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。