妈妈再也不担心我的数据丢失了——文件操作:使数据能够持久化

前言:在使用电脑时,我们常常能看见一大堆文件,那么你知道什么是文件吗?你知道如何进行文件操作吗?在本章,将教大家一些简单的文件操作方法。

1.什么是文件?

存在磁盘中的文件就是文件。
在程序设计中,一般有两种文件:程序文件、数据文件(从文件功能角度来分类)。

1.1程序文件

包括源程序文件.c、目标文件.obj、可执行文件.exe等。

1.2数据文件

文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行时需要从中读取数据的文件或者输出内容的文件。

本章讨论的是数据文件。如果想了解一些程序文件的知识的话,请看这篇博客:翻译环境和执行环境

1.3文件名

文件名包含3部分:文件路劲+文件名主干+文件后缀,例如:C:\android\text.txt,同时,为了方便起见,文件标识常被称为文件名。

2.为什么使用文件?

常规情况下写出来的代码数据都是放在内存上的,退出程序就销毁了。想要将数据持久化,就要将数据放在磁盘上,这就是为什么电脑的盘中有那么多文件。

3.文件的打开和关闭(重点)

问:假如我们想从冰箱中拿一个西瓜,有几个步骤呢?首先需要打开冰箱门,然后从中拿出西瓜,最后再关上冰箱门。
文件的使用与这是类似的:首先要打开文件,然后对文件进行操作,最后关闭文件。

3.1文件指针的概念

想要进行文件操作,首先得知道什么是文件指针

缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态以及文件当前的位置等等)。这些信息是保存在一个结构体变量中的。改结构体类型是由系统声明的,取名FILE

3.2fopen/fclose函数

fope:打开文件
fclose:关闭文件
fopen,fclose的使用方式和动态数组开辟中的malloc/free函数非常相似,有此基础的朋友理解起来相信会很轻松。

fopen函数

在这里插入图片描述
fopen函数的第一个参数为想要打开的文件,第二个参数为文件使用方式。
注意它的类型是FILE*,并且两个参数都需要用""括起来。

fclose函数

在这里插入图片描述
fclose函数相对简单,只需要输入想要关闭的文件流即可。

文件使用模式

这里的文件使用方式又是一个大家陌生的知识点,下面给大家普及几种常见的文件使用模式:
在这里插入图片描述

这里举个例子:方便大家明白具体该如何使用fopen和fclose函数。

#include<stdio.h>
int main()
{
    
    
	//打开文件,创建一个FILE*变量,这里我设置的文件没有具体路径,默认在当前路径底下,用"w"方式打开文件
	FILE* pf = fopen("text.txt", "w"); 
	//判断文件是否创建成功,记住该格式即可。
	if (pf == NULL)
	{
    
    
		perror("Error opening file");
	}
	//关闭文件
	fclose(pf); 
	pf = NULL;
	return 0;
}

上述代码运行之后,再在当前文件目录底下查看,我们会发现多了一个text.txt的文件,双击打开文件后会发现里面什么都没有,因为我们还没有对它进行输入输出操作。
在这里插入图片描述

到这里,相信你们就学会了文件的打开和关闭。我们继续向下学习。

4.文件顺序读写(重中之重)

上面我们了解了文件的打开和关闭,这里将介绍它们的中间环节——文件输入输出操作。

4.1标准/文件流输入输出对比

下图1为标准输入输出图,图2为文件流输入输出图。
该类比图对于下面的顺序读写函数的理解非常有帮助。
许多人会在这里产生疑惑:比如我们想在文件中写数据,用的是fputc函数,而这与标准流中put函数的逻辑是相反的,put函数是将数据打印出来。这种时候就可以看看看看下图2.
记住:写文件——输出读文件——输入
这里是引用

4.2顺序读写函数

下列的函数能够适用于文件流的输入输出,大体上与标准输入输出函数很相似。跟之前一样,还是带大家看几个函数的具体使用例子,便于大家了解掌握。

在这里插入图片描述

fputc函数

在这里插入图片描述
fputc函数具有两个参数,第一个为想输出的字符,第二个为文件流。

问:假如想在文件中输出26个英文字母,该怎么用fputc实现?

#include<stdio.h>
int main()
{
    
    
	FILE* pf = fopen("text.txt", "w"); 
	if (pf == NULL)
	{
    
    
		perror("Error opening file");
	}
	//实现部分
	for (int i = 0; i < 26; i++)
	{
    
    
		fputc('a'+i, pf); 
	}
	
	fclose(pf);
	pf = NULL;
	return 0;
}

执行代码后,我们再在当前文件路径底下打开text.txt文件,会发现文件里面显示了26个英文字母。
在这里插入图片描述

fgetc函数

在这里插入图片描述
fgetc函数只有一个参数,即将要输入的文件流。

问:刚刚我们在文件text.txt中输出了26个英文字母,该怎么读取文件输入它们呢?

#include<stdio.h>
int main()
{
    
    
	FILE* pf = fopen("text.txt", "r"); //!!!因为要读取文件,所以这里文件操作方式变为''r''
	if (pf == NULL)
	{
    
    
		perror("Error opening file");
	}
	for (int i = 0; i < 26; i++)
	{
    
    
		int ret = fgetc(pf);  //fgetc返回值是int类型,所以创建一个int类型的变量接收它的返回值。
		printf("%c ", ret);   //打印
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

代码执行后终端显示如下:上述代码我们并没有进行26个英文字母的赋值操作,而是直接从文件中读取数据
在这里插入图片描述

fprintf函数

适用于所有流的格式化输出函数
这里是引用
fprintf函数具有两个参数,第一个为文件流,第二个与标准输入函数scanf的参数一样。
使用fprintf函数时,可以先当作printf将第二个参数写出来,最后再加上第一个参数文件流。

问:怎么将一个结构体变量写到文件中?

#include<stdio.h>
struct stu   //创建一个stu结构体
{
    
    
	char name[10];
	char sex[5];
	int age;
};
int main()
{
    
    
	struct stu S1 = {
    
     "zhangsan","nan",25 };
	FILE* pf = fopen("text.txt", "w"); //写文件“w”
	if (pf == NULL)
	{
    
    
		perror("Error opening file");
	}
	fprintf(pf,"%s %s %d", S1.name, S1.sex, S1.age);//输出到文件中
	fclose(pf);
	pf = NULL;
	return 0;
}

代码执行后打开文件text.txt文件显示如下:可以感觉fprintf使用起来与我们经常使用的标准输出函数printf差别不大。
在这里插入图片描述

fscanf函数

适用于所有流的格式化输入函数 在这里插入图片描述
与上面的fprintf类似,第一个参数为文件流,第二个参数与标准输入函数scanf参数一样。

问:怎么将刚刚写到文件中的结构体打印出来?相信这个问题肯定难不到看到这里的各位

#include<stdio.h>
struct stu 
{
    
    
	char name[10];
	char sex[5];
	int age;
};
int main()
{
    
    
	struct stu S = {
    
     0 };  //创建一个结构体变量
	FILE* pf = fopen("text.txt", "r"); //读文件
	if (pf == NULL)
	{
    
    
		perror("Error opening file");
	}
	fscanf(pf,"%s%s%d", S.name, S.sex, &(S.age)); //将文件中数据输入到内存中
	printf("%s %s %d", S.name, S.sex, S.age);  //打印
	fclose(pf);
	pf = NULL;
	return 0;
}

代码执行后终端显示如下:
在这里插入图片描述

顺序读写函数就展示到这里了,如果各位读者对其它函数也很感兴趣的话,可以去cplusplus网站,里面对函数的介绍很详细,并且都有例子方便读者了解。

至此,文件3步骤就学完了,快去实践实践吧。

文末BB:对哪里有问题的朋友,可以在评论区留言,若哪里写的有问题,也欢迎朋友们在评论区指出,博主看到后会第一时间确定修改。最后,制作不易,如果对朋友们有帮助的话,希望能给点点赞和关注.
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_73390155/article/details/130116690