当前位置: 首页 > news >正文

【文件指针+文件顺序读写操作函数】

1.文件的打开和关闭

  • 1.1 什么是文件指针

2.文件操作函数

  • 2.1 fgetc函数和fputc函数
  • 2.2 fgets函数和fputs函数
  • 2.3 fscanf函数和fprintf函数
  • 2.4 fwrite函数和fread函数

1.文件的打开和关闭

1.1 什么是文件指针?

每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名
字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统
声明的,取名FILE.

假如:我们要操作一个文件,名为text.txt ,首先要打开文件,打开文件的同时,操作系统会自动为该文件创建一个文件信息区,专门用来记录该文件的信息。

在这里插入图片描述
文件信息区的每一个信息与text.txt的信息是一一对应的。而该文件信息区名为struct _iobuf,又被重命名为 FILE 。

所以FILE其实就是文件信息区。

每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,使用者不必关心细节。

一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。

下面我们可以创建一个FILE*的指针变量:

FILE* pf; 文件指针变量

通过该文件指针变量,我们就可以读写文件中的信息。

文件在读写之前,需要打开文件

//打开文件
FILE * fopen ( const char * filename, const char * mode );

读写文件完成后,需要关闭文件:

//关闭文件
int fclose ( FILE * stream );

文件的打开方式如下:

在这里插入图片描述
举个例子:

#include <stdio.h>
int main ()
{
 //打开文件
FILE* pFile = fopen ("text.txt","w");
 //文件操作
 if (pFile!=NULL)
{
  fputs ("fopen",pFile);
  //关闭文件
  fclose (pFile);
}
 return 0;
}

该段代码的意思是:打开一个文件叫text.txt,以写的形式打开。意味着向文件中写入信息。具体是怎么写的,下面会讲到。
写完信息后关闭文件,fclose(pFile),pFile就是一个文件指针。

文件指针就是用来操作文件的,假如我们需要对文件进行写入的操作,就使用文件指针打开该文件并定义"写"的操作。

2.文件操作函数

在这里插入图片描述

2.1 fgetc函数和fputc函数

fgetc函数和fputc函数是针对字符的输入输出的。

int fgetc(FILE* stream);
//从流中读取字符,返回读到的ascii码值

流是什么呢?可以把流理解成水流,水流到尽头,就是一个蓄水池。一个蓄水池就相当于一个存储大量文件的区域。文件也类似,从流中(文件信息区)中读取文件,fgetc返回读到的ascii码值。

int fputc(int character, FILE* stream);
//把字符character 写入流中

fputc是将一个字符写入文件中。一次写入一个字符,返回成功写入的字符的个数。

举个例子:

int main()
{
	FILE* pf =fopen("text.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	//写入字符
	char ch = 0;
	for (ch = 'a'; ch <= 'z'; ch++)
	{
		fputc(ch, pf);
	}

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

先打开text.txt文件,如果不存在该文件,则会新建一个文件("w"写入的形式会新建一个文件,但是以"r"的形式打开文件,如果文件不存在,会读取文件失败,返回NULL)

然后向文件中写入a~z个字母。

运行成功,成功写入文件:
在这里插入图片描述

写入成功,现在向文件中读取数据

int main()
{
	FILE* pf = fopen("text.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	//写入字符
	char ch = 0;
	for (ch = 'a'; ch <= 'z'; ch++)
	{
		int ch = fgetc(pf);
		printf("%c ", ch);
	}

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

读取成功,如下图:
在这里插入图片描述
总结:fgetc函数是向文件指针pf(或者其他名字,由你来定)一次读取一个字符,读取完第一个字符后,指针自动跳到下一个字符。
fputc函数是向pf指向的指针一次写入一个字符。

2.2 fgets函数和fputs函数

int fputs(const char* str, FILE* stream);
向流中写入一行数据,一次性写一行

举个例子:

int main()
{
	FILE* pf = fopen("text.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	fputs("Hello World","w"); 
	
	fclose(pf);
	pf = NULL;
	return 0;
}

写入成功。
在这里插入图片描述
注意:打开文件进行写入操作时,上一次写入的数据将会被清除。

接下来向从文件中读取数据:

int main()
{
	FILE* pf = fopen("text.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	//读文件,一次读一行
	char buf[20];
	fgets(buf, 10, pf); // 读10个字节,相当于读9个,最后一个字节留着放\0
	printf("%s\n", buf);
	fclose(pf);
	pf = NULL;
	return 0;
}

注意:当我们读取10个字节时,实际上打印出来只打印前面9个字节的内容,还有一个字节是被用来留着放\0的。

还有一种情况,假如我们需要读取20个字节的数据,然而第一行不足20个字节,fgets读完所有的数据后,即使不够20个字节,就不会再读取了,就停止了。不会跳到第二行继续读。 更说明fges是一次只读取一行。

2.3 fscanf函数和fprintf函数

前面说过,fscanf函数和fprintf函数是格式化输入输出函数。什么是格式化函数呢?
其实格式化函数就是对于不同格式的数据都能够进行输入输出,比如:整型,浮点型,结构体类型等等,这些就是不同格式的数据。

相较于scanf和printf函数,fscanf函数和fprintf只是多了一个参数,即FILE指针所指向的文件。fscanf函数是向FILE的指针指向的文件中读取格式化的数据,fprintf函数是向FILE*的指针指向的文件中写入格式化的数据。

对比如下:

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

举一个简单的例子:
向text.txt文件中写入结构体数据

int main()
{
	FILE* pf = fopen("text.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	struct S
	{
		char name[20];
		int age;
		float score;
	}s = {"zhangsan",20,99.5f};
	fprintf(pf,"%s %d %f", s.name, s.age, s.score);
	
	fclose(pf);
	pf = NULL;
	return 0;
}

运行成功后,文件中就有了该结构体的数据。

在这里插入图片描述
对于fscanf来说亦是如此:

在这里插入图片描述
以读的方式打开该文件,对其中的数据进行读取。读取后,打印出来看即可。

s.name不用&的原因是,s.name是一个数组名,表示首元素地址,不需要&,而其他的age和score则需要&。

前面说过,这几个函数都是适用于所有输入流输出流,那么就包括了键盘(标准输入流),屏幕(标准输出流)。

int main()
{
	int ch = fgetc(stdin);
	fputc(ch, stdout);
}

此时,我们会从键盘中读取一个字符,写入到屏幕中。
在这里插入图片描述
对于其他函数也是如此。仍可以从键盘中读取数据,写入到屏幕上。

2.4 fwrite函数和fread函数

上面提到,fwrite函数和fread函数是以二进制的形式进行写入和读取的。

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

先来看看fwrite在库中的声明。
fwrite函数是向stream这个流中一次写count个大小为size的ptr指向的内容。
看不懂没关系,举个例子:

typedef struct S
{
	char name[20];
	int age;
	float score;
}S;

int main()
{
	S s = { "zhangsan",20,95.5f };
	FILE* pf = fopen("text.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	fwrite(&s, sizeof(S), 1, pf);
	
	fclose(pf);
	pf = NULL;
	return 0;
}

此时我们创建了一个结构体,该结构体有三个成员,我们以二进制写入的形式打开文件进行写入,此时向pf指向的文件中写入s这块空间,一次写入1个sizeof(S)大小的内容。

运行成功后,打开text.txt文件:
在这里插入图片描述

你会发现出了拼音zhangsan,其他的都看不懂,没关系,因为这是二进制形式。
看不懂并不代表代码是错误的。

既然我们看不懂,我们就让编译器来看,下面我们以二进制读取的方式,向文件中读取数据出来。

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

既然是读取,那么就是跟写入相反而已。
从stream流指向的文件中读取ptr这块空间的内容,一次读取count个大小为size个字节的内容。

typedef struct S
{
	char name[20];
	int age;
	float score;
}S;

int main()
{
	S s = { 0 };
	FILE* pf = fopen("text.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	fread(&s, sizeof(S), 1, pf);
	printf("%s %d %f", s.name, s.age, s.score);

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

此时我们向pf流指向的文件中读取s这块空间的内容,一次读取1个大小为sizeof(S)个字节的内容。读取成功后,我们就打印出来看看。
在这里插入图片描述
打印结果确实符合预期。

总结:fwrite 和fread函数是向文件中以二进制的形式写入和读取文件的。

相关文章:

  • 手机如何做网站/百度推广北京总部电话
  • wordpress in/青岛seo网站关键词优化
  • 游戏网站制作模板/百度热搜榜排名昨日
  • 制作企业网站页面实训报告/河南seo技术教程
  • 泉州网站设计平台/推广优化网站排名
  • 网站建设哪里找/seo工具软件
  • Java分割字符串(spilt())
  • git使用(复健 1 )
  • 2022视频编码招聘面经
  • Python爬虫 Selenium(六)
  • Day54 跨域CORS资源JSONP回调域名接管劫持
  • Doris 使用记录(随机更新(ง •_•)ง)
  • 软考初级哪个好考
  • 套接字编程(二)UDP服务端与客户端的通信模拟实现
  • 【电子学会】2022年12月图形化四级 -- 金牌百分比
  • Pandas 数据结构 - Series
  • ESP32 FreeRTOS-消息缓冲区(13)
  • Leetcode刷题Day26休息Day27------------------回溯算法