文件操作【C语言】

在这里插入图片描述



1️⃣前言

在C语言的学习中,对于文件的操作是必不可少的,善于对文件进行操作可以帮助我们在运行程序时省去很多麻烦。例如我们可以把数据保存到文件中,当我们在运行程序时直接从文件中导入数据就避免了每次运行程序时都要先输入数据这一步骤。像是我们在做一些通讯录这样的小程序,都可以用到我们的文件这一操作,下面我们就来介绍一下C语言中对文件的一些操作。

对文件进行操作大致可以分为3大步骤:

1.打开文件
2.操作
3.关闭文件

下面我们就分这么3大步来对我们的文件进行分析。

2️⃣ 文件的打开和关闭

▶️文件指针

当我们想要对文件进行操作时,绕不开的是我们的文件指针。在缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是由系统声明的,取名FILE。我们一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。因此我们首先就需要来定义一个FILE*的指针变量,如下代码:

FILE* pf;

定义pf是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它关联的文件。

🅿️打开文件

文件在读写之前应该先打开文件。在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。ANSIC 规定使用fopen函数来打开文件。
fopen函数传送门

FILE * fopen ( const char * filename, const char * mode );

文件的打开如果失败则返回一个NULL指针,成功的话返回一个指向文件内容起始位置的指针。文件的打开方式有多种,如下表:

文件使用方式含义如果指定文件不存在
“r”(只读)为了输入数据,打开一个已经存在的文本文件出错
“w”(只写)为了输出数据,打开一个文本文件建立一个新的文件
“a”(追加)向文本文件尾添加数据建立一个新的文件
“rb”(只读)为了输入数据,打开一个二进制文件出错
“wb”(只写)为了输出数据,打开一个二进制文件建立一个新的文件
“ab”(追加)向一个二进制文件尾添加数据出错
“r+”(读写)为了读和写,打开一个文本文件出错
“w+”(读写)为了读和写,建议一个新的文件建立一个新的文件
“a+”(读写)打开一个文件,在文件尾进行读写建立一个新的文件
“rb+”(读写)为了读和写打开一个二进制文件出错
“wb+”(读写)为了读和写,新建一个新的二进制文件建立一个新的文件
“ab+”(读写)打开一个二进制文件,在文件尾进行读和写建立一个新的文件

📶关闭文件

ANSIC 规定使用fclose函数来关闭文件。
fclose函数传送门

int fclose ( FILE * stream );

文件的打开和关闭总是成对出现,当我们打开了一个文件并完成一系列的操作后,我们千万要记得关闭文件,打开和关闭文件代码示例如下:

#include <stdio.h>
int main()
{
    FILE* pFile;
    //打开文件
    pFile = fopen("test.txt", "w");
    //判断
    if (pFile == NULL)
    {
        printf("打开失败!\n");
        exit(-1);
    }
    //文件操作
    //略。。。
  
    //关闭文件
    fclose(pFile);
    pFile = NULL;
    return 0;
}

上述代码中,我们创建了一个pFile的指针,并使用fopenw只写的方式打开了一个名为test.txt的文件,如果打开失败fopen返回一个空指针给pFile,因此我们在后面紧跟着就是对文件打开成功与否进行判断,打开成功的话我们就继续进行后面的文件操作,操作完成后接下来就是使用fclose关闭文件,然后将pFile置空。

3️⃣文件操作

对文件的操作我们有以下几种函数可以使用,如下表:

功能函数名适用于
字符输入函数fgetc所有输入流
字符输出函数fputc所有输出流
文本行输入函数fgets所有输入流
文本行输出函数fputs所有输出流
格式化输入函数fscanf所有输入流
格式化输出函数fprintf所有输出流
二进制输入fread文件
二进制输出fwrite文件

我们可以看到这几种输入输出函数也是成双成对出现的,下面我们就一一对这四对函数进行分析。在分析这四组函数前,我们首先需要搞清楚输入输入的含义,当我们就字面看到的输入输出我们很有可能理解为输入就是从内存中输入到文件,输出就是从文件中输出到内存。如果我们是这样理解的话,那就恰恰相反了,我们所说的输入是从文件输入到内存,我们也可以把这个操作称为操作。输出是从内存输出到文件,我们也可以把这个操作称为操作。我们也可以用画图来更加清晰的表示,如下图。
在这里插入图片描述

⏪字符输入输出函数

fputc为字符输出函数,可以进行写操作,将字符一个一个的写进文件里。

👉fputc函数传送门

int fputc ( int character, FILE * stream );

我们通过以下代码来分析fputc函数。

#include <stdio.h>
int main()
{
	char arr[] = "abcdefg";
	FILE* p = fopen("text.txt", "w");
	if (p == NULL)
	{
		printf("打开失败!\n");
		exit(-1);
	}
	for (int i = 0; i < 26; i++)
	{
		fputc('a' + i, p);
	}
	fclose(p);
	p = NULL;
	return 0;
}

代码中,我们利用for循环和fputc函数将26个字母依次写入到名为text.txt文件中,在程序运行完成后我们可以打开该文件观察,如下图所示:

在这里插入图片描述
在进行完写操作,我们还可以用fgetc进行读操作。


fgetc为字符输入函数,可以进行读操作,将字符一个一个的从文件读到内存中来,并且指针指向下一个数据。

👉fgetc函数传送门

int fgetc ( FILE * stream );

代码分析:

#include <stdio.h>
int main()
{
	char arr[] = "abcdefg";
	FILE* p = fopen("text.txt", "r");
	if (p == NULL)
	{
		printf("打开失败!\n");
		exit(-1);
	}
	for (int i = 0; i < 26; i++)
	{
		printf("%c ", fgetc(p));
	}
	printf("\n");
	fclose(p);
	p = NULL;
	return 0;
}

代码中,我们利用for循环和fgetc函数将26个字母依次从text.txt文件读出到内存中,然后我们用printf打印出来,在程序运行后我们可以观察结果,如下图所示:

在这里插入图片描述

ℹ️文本行输入输出函数

fputs是文本输出函数,可以进行文件写操作,可以将字符串写进文件中。

👉fputs函数传送门

int fputs ( const char * str, FILE * stream );

fputs函数的作用是将str指针所指着的数据写入到stream文件指针指着的文件中去。

代码分析:

#include <stdio.h>
int main()
{
	FILE* p = fopen("text.txt", "w");
	if (p == NULL)
	{
		printf("打开失败!\n");
		exit(-1);
	}
	fputs("hello\n", p);
	fputs("world", p);
	fclose(p);
	p = NULL;
	return 0;
}

代码中,我们用fputs函数分别将helloworld写进文件,其中hello字符串中的\n也被写进了文件中,在文件中起到了换行的作用,我们运行完代码后可以打开文件观察内容,如下图:

在这里插入图片描述


fgets为文本输入函数,可以进行读操作,将文件中的数据一行一行的读出来,读完一次后指针会自动指向下一行。

👉fgets函数传送门

char * fgets ( char * str, int num, FILE * stream );

fgets函数是将文件中的一行数据以最大num个读出来后存放到str数组中,如下代码:

#include <stdio.h>
int main()
{
	char arr[] = "################";
	FILE* p = fopen("text.txt", "r");
	if (p == NULL)
	{
		printf("打开失败!\n");
		exit(-1);
	}
	fgets(arr, 5, p);
	fclose(p);
	p = NULL;
	return 0;
}

代码中,我们定义了一个arr数组,在上面我们就已经给text.txt文件中写入了内容,所以这里我们就直接进行读操作就行了,我们用fgets函数从文件中读出最多5个字符存放到arr数组中。fgets函数进行一次操作后会自动跳到下一行,其中当文件中一行的数据量大于最大读取数num时,实际读取到的数据个数为num-1个,最后一个会在后面补上一个\0,如下图:

在这里插入图片描述
当文件中一行的数据量小于读取数num时,则实际读取到的个数为这一行的个数加上\0,如果有\n的话,\n也会被读取,如下图:

在这里插入图片描述

🛂格式化输入输出函数

fprintf为格式化输出函数,可以进行文件的操作,将内存中的数据写入到文件中去

👉fprintf函数传送门

int fprintf ( FILE * stream, const char * format, ... );

fprintf函数和printf函数非常的相似,fprintf的前面多了一个文件指针,表示把数据以某种格式写入到文件指针所指着的文件中去,具体如下代码演示:

#include <stdio.h>
int main()
{
	FILE* p = fopen("text.txt", "w");
	if (p == NULL)
	{
		printf("打开失败!\n");
		exit(-1);
	}
	int i = 5;
	char arr[] = "abcdef";
	fprintf(p, "%d %s", i, arr);

	fclose(p);
	p = NULL;
	return 0;
}

代码中我们用fprintf将整型i和字符串arr分别以%d%s的格式写入到p指针指着的文件中去,运行后我们可以打开文件查看,如下图:

在这里插入图片描述


fprintf相对应的fscanf可以完成文件的操作,可以把数据从文件中以格式化的形式读取到内存中来。

👉fscanf函数传送门

int fscanf ( FILE * stream, const char * format, ... );

fscanfscanf函数相似,是以某种格式将数据从文件中读取出来,具体功能如下代码:

#include <stdio.h>
int main()
{
	FILE* p = fopen("text.txt", "r");
	if (p == NULL)
	{
		printf("打开失败!\n");
		exit(-1);
	}
	int x = 0;
	char arr[] = "#########";
	fscanf(p, "%d %s", &x, arr);

	fclose(p);
	p = NULL;
	return 0;
}

代码中我们利用fscanf函数将文件中的整型5和字符串abcdef分别以%d%s的形式读出来并存放到x变量和arr数组中去,我们可以调试观察结果,如下图所示:

在这里插入图片描述

🔁二进制输入输出函数

与上面介绍的几个输入输出函数不同,上面介绍的几种输入输出函数适用于所有的输入输出流,而我们下面介绍的二进制输入输出函数适用于文件操作,并且是以二进制的形式进行读写。

👉fwrite函数传送门

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

fwrite函数的作用是将ptr指针所指的数据以size个字节读取count次并写入到stream指针指向的文件中去,如下代码:

#include <stdio.h>

struct people
{
	char name[20];
	int age;
};
int main()
{
	FILE* p = fopen("text.txt", "wb");
	if (p == NULL)
	{
		printf("打开失败!\n");
		exit(-1);
	}
	struct people peop = { "wang", 15 };
	fwrite(&peop, sizeof(peop), 1, p);

	fclose(p);
	p = NULL;
	return 0;
}

代码中我们定义了一个结构体并且创建了一个结构体变量peop后进行赋值,然后利用fwrite函数将结构体写入到文件中,运行后观察文件中内容如下图:

在这里插入图片描述

因为fwrite函数是以二进制形式进行写操作,所以在文件中可能会有我i们看不懂的字符。


fwrite函数相对应的二进制输入函数fread,可以进行文件读操作。

👉fread函数传送门

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

fread函数与fwrite函数类似,将stream指针指向的文件中的数据以size个字节读取count次然后放入到ptr指针指向的内存中去,如下代码:

#include <stdio.h>

struct people
{
	char name[20];
	int age;
};
int main()
{
	FILE* p = fopen("text.txt", "rb");
	if (p == NULL)
	{
		printf("打开失败!\n");
		exit(-1);
	}
	struct people peop;
	fread(&peop, sizeof(peop), 1, p);

	fclose(p);
	p = NULL;
	return 0;
}

代码中我们创建了一个结构体变量peop用于存放读取到的数据,然后利用fread函数将文件中的数据以二进制的形式读取出来,我们调试观察结果,如下图所示:

在这里插入图片描述

4️⃣总结

文章中介绍了文件的基本操作,包括文件的打开关闭和文件的操作,文件的操作我们又介绍了几组文件的输入输出函数,大家看完如果觉得还不错的话就来个一键三连吧😁 !另外如果文章中出现错误或者纰漏还望指正,欢迎在评论区中评论。

在这里插入图片描述

  • 42
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 55
    评论
评论 55
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拖拉机厂第一代码手

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值