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

news2025/1/11 20:03:34

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函数是向文件中以二进制的形式写入和读取文件的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/167829.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

文件操作详解

文章目录前言一、什么是文件&#xff1f;1.程序文件2.数据文件3.文件名二、文件的打开和关闭1.文件指针2.文件的打开和关闭3.打开模式汇总4.例子三.操作函数介绍1.基本函数2.fseek2.ftell3.rewind4.feof尾话前言 恐怕很多人学完了c语言甚至不知道文件操作&#xff0c;也确实&am…

FPGA学习笔记-知识点3-Verilog语法1

1.关键字 2.运算符 按其功能可分为以下几类: 1) 算术运算符(,&#xff0d;,&#xff0c;/,&#xff05;) 2) 赋值运算符(,<) 3) 关系运算符(>,<,>,<) 4) 逻辑运算符(&&,||,!) 5) 条件运算符( ? &#xff1a;) 6) 位运算符(,|,^,&,^) …

【微信小程序】动态设置导航栏标题

&#x1f3c6;今日学习目标&#xff1a;第十八期——动态设置导航栏标题 &#x1f603;创作者&#xff1a;颜颜yan_ ✨个人主页&#xff1a;颜颜yan_的个人主页 ⏰预计时间&#xff1a;25分钟 &#x1f389;专栏系列&#xff1a;我的第一个微信小程序 文章目录前言使用配置文件…

消息中间件简介

UNIX的进程间通信就开始运用消息队列技术&#xff0c;一个进程将数据写入某个特定的队列中&#xff0c;其它进程可以读取队列中的数据&#xff0c;从而实现异步通信。对于如今的分布式系统&#xff0c;消息队列已经演变为独立的消息中间件产品&#xff0c;相比于RPC同步通信的方…

设计模式_行为型模式 -《模板方法模式》

设计模式_行为型模式 -《模板方法模式》 笔记整理自 黑马程序员Java设计模式详解&#xff0c; 23种Java设计模式&#xff08;图解框架源码分析实战&#xff09; 行为型模式用于描述程序在运行时复杂的流程控制&#xff0c;即描述多个类或对象之间怎样相互协作共同完成单个对象都…

测试开发 | AppCrawler 自动遍历测试实践(三):动手实操与常见问题汇总

上两篇文章介绍了自动遍历的测试需求、工具选择和 AppCrawler 的环境安装、启动及配置文件字段基本含义&#xff0c;这里将以实际案例更加细致的说明配置文件的用法和一些特殊场景的处理。 实操演示 常规使用 下面我们继续之前的例子&#xff0c;在雪球搜索框输入搜索内容后的页…

代码随想录算法训练营第六天 | 哈希表理论基础,242.有效的字母异位词,349. 两个数组的交集, 202. 快乐数,1. 两数之和

第五天 周日 休息~【提醒补坑&#xff1a;链表总结还没写】一、参考资料哈希表理论基础文章连接&#xff1a;https://programmercarl.com/%E5%93%88%E5%B8%8C%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html有效的字母异位词题目链接/文章讲解/视频讲解&#xff1a;https:…

使用批处理__更改ip

1、使用.bat进行处理 echo off rem 测试更改ip netsh int ip set address "以太网 2" static 10.10.2.1 255.255.255.0 10.10.2.254 1 pause&exit 备注其他 echo #设静态IP netsh interface ip set address name"本地连接" sourcestatic addr192.16…

大坝安全监测解决方案 水库大坝安全监测系统改造工程方案

平升电子大坝安全监测系统根据SL551-2012《土石坝安全监测技术规范》的整编要求&#xff0c;设置了变形监测、渗流监测、环境量监测。借助大坝安全监测系统可及时了解大坝的工作性态和水库可能存在的事故隐患&#xff0c;为大坝安全管理与水库运行调度提供了准确、及时的现场信…

ElasticSearch7.10配置Search-Guard之配置用户

ElasticSearch7.10配置Search-Guard之配置用户 配置sg_internal_user.yml 密码是&#xff1a;elastic jode:hash: $2y$12$nUzkcjdnufzvI1HlmN7xSuND3skGhmwV5le5IINejz.asMFpLYNRybackend_roles:- "hr_department"psmith:hash: $2y$12$nUzkcjdnufzvI1HlmN7xSuND3sk…

[标准库]STM32F103R8T6 标准库配置RCC时钟和超频

前言 这篇博客总结一下学习到的配置时钟的方法。 从启动文件来看&#xff0c;MCU复位之后&#xff0c;执行到SystemInit()这个函数之后&#xff0c;会进入系统初始化设置&#xff0c;比如根据当前的MCU型号进入不同的条件编译语句&#xff0c;再配置相应的寄存器初始值&#…

mysql之一条mysql语句时如何执行的

请把连接器的功能说明一下? 连接器负责建立客户端和mysql服务器之间的连接.当客户端在中断输入连接命令(mysql -h -u -p),传输层使用tcp协议,通过三次握手建立连接. 如果mysql服务服务没有启动,会报错: 如果mysql服务正常启动,完成三次握手,在传输层建立连接后,会进行密码验证…

【云原生】k8s 一键部署(ansible)

文章目录一、概述二、Ansible 部署1&#xff09;开启记录日志2&#xff09;去掉第一次连接ssh ask确认3&#xff09;配置hosts三、开始编排 ansible playbook1&#xff09;创建目录2&#xff09;节点初始化3&#xff09;安装 docker4&#xff09;安装 k8s 相关组件5&#xff09…

2022 年 12 月区块链操作系统的开发回顾

正在寻找区块链操作系统组件的最新进展&#xff1f;你找对地方了&#xff01;正如在我们的路线图文章中所描述的那样&#xff0c;我们一直在朝着定期且频繁的更新方向发展着&#xff0c;以便让我们的社区能够及时的了解到我们取得的进展&#xff0c;以及将区块链操作系统提升到…

新年喜报 再添殊荣 加速科技荣获浙江省“专精特新”企业认定

新年伊始&#xff0c;杭州市经济和信息化局公布了2022年度浙江省专精特企业名单。杭州加速科技有限公司&#xff08;以下简称“加速科技”&#xff09;凭借在技术创新、产品研发、精细化程度、经营能力、拓展潜力等多方面的优势&#xff0c;荣获浙江省“专精特新”企业荣誉称号…

一个人,一座城,你到底在乎什么?Python 爬虫告诉你!

大家好&#xff0c;我是安果&#xff01;有时候&#xff0c;我们想知道生活在这座城市的人每天交流的事情&#xff0c;然后对数据进行一些分析&#xff0c;方便我们更好地了解城市的特征及居民的需求以重庆为例&#xff0c;最火爆的论坛是购物狂&#xff0c;每天都有大量的帖子…

求解带不确定事件的FJSP的多目标强化学习框架

文献&#xff1a;Hao Wang, Junfu Cheng, Chang Liu, Yuanyuan Zhang, Shunfang Hu, Liangyin Chen,Multi-objective reinforcement learning framework for dynamic flexible job shop scheduling problem with uncertain events,Applied Soft Computing,Volume 131,2022,1097…

超级详细的python知识点及练习题(附答案)

今天咱们继续来学习python的小知识吖&#xff0c;上一次木有看的同学请看&#xff1a;python8大核心语句 作者&#xff1a;阿玥的小东东 学习&#xff1a;python&#xff0c;正在学习c 主页&#xff1a;阿玥的小东东 目录 1.复习及易错&#xff0c;快来学习&#xff01;&#…

基于python手撕实现BP 神经网络实现手写数字识别

本项目使用python实现全连接网络和梯度优化 方向传播并且实现了 手写数字识别项目: 神经网络 model 先介绍个三层的神经网络,如下图所示输入层(input layer)有三个 units( 为补上的 bias,通常设为

线程池ThreadPoolExecutor源码解析

参考视频 首先回顾一下创建线程等的三种方式 第一个是直接继承Thread类&#xff0c;重写run方法&#xff0c;这个其实内部也是继承了Runnable接口重写run方法。 比如&#xff1a; public class MyThread extends Thread{Overridepublic void run() {System.out.println("…