C语言中常用的文件操作

本文将介绍常用的关于文件操作函数,如fopen,fclose,fread,fwrite,feek,ftell,rewind以及feof和ferror等文件操作操作函数,还介绍一些用于所有输入输出流的函数如fgetc,fputc,fgets,fputs,fprintf,fscanf等函数,还介绍了sscanf,sprintf函数,feof和ferror函数。最后介绍了文件文件缓冲区的存在。

目录

1、文件的介绍

2、文件的打开和关闭

①流的介绍

②文件指针

③文件的打开和关闭

④顺序读写函数介绍 

(1)fgetc函数介绍

(2) fputc函数介绍

(3)fgets函数介绍

(4)fputs函数介绍

(5)fscanf函数介绍

(6)fprintf函数介绍

(7)fwrite函数介绍

(8)fread函数介绍

3、scanf,printf,sscanf,sprintf,fscanf,fscanf函数的区别

(1)sscanf函数介绍

(2)sprintf函数介绍

4、文件的随机读写

(1)ftell函数介绍

(2)rewind

5、文件读取结束的判定 

feof函数介绍

ferror函数介绍

6、文件缓冲区


1、文件的介绍

我们写的程序的数据是存储在电脑的内存中,当程序退出,内存回收,数据就会丢失,当再次想要看到上次程序的结果是看不到的,想要将数据进行持久化的保存(程序退出其数据不丢失),我们可以使用文件来对这些数据进行保存。

从文件功能方面来分类,文件有程序文件和数据文件。程序文件包括源程序文件(如后缀为.c文件),目标文件(Windows系统其后缀名为.obj),可执行文件(Windows系统下其后缀名为.exe)。数据文件,其文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件或输出内容的文件。下面介绍的是数据文件。根据数据的组织形式,数据文件被称为二进制文件和文本文件,如果数据在内存中以二进制的形式存储(不经任何转换),直接输出到外存文件中,这就是二进制文件。如果在外存中以ASCII码的形式存储,在存储前需要进行转换,以ASCII码的形式存储的文件就是文本文件。数据存储到外存的这个文件即可以二进制的形式进行存储也可以ASCII码的形式进行存储。这个区分主要是看这个外存(硬盘)里的存储的是二进制还是ASCII码的形式。注意,计算机中的数据在内存中都是二进制进行存储的,是文本文件还是二进制文件是针对外存(也就是硬盘来说的)。

2、文件的打开和关闭

①流的介绍

程序的数据可能会输出到各种外部设备,也可能从外部设备获取数据,不同的外部设备的输入输出操作各不相同,为了方便程序员对各种设备进行方便的操作,所以就抽象出来了流的概念。C语言程序对文件,画图,键盘等数据的输入操作都是通过流操作的。一般情况下,要想向流里写数据或者从流中读取数据都是要打开流然后进行操作。

值得注意的是,从键盘输入数据和向屏幕里打印信息都没有打开流,这是由于C语言程序在启动的时候默认打开了3个流(stdin,stdout,stderr)。

stdin - 标准输⼊流,在⼤多数的环境中从键盘输⼊,scanf函数就是从标准输入流中读取数据。
stdout - 标准输出流,大多数的环境中输出⾄显⽰器界⾯,printf函数就是将信息输出到标准输出
流中。
stderr - 标准错误流,大多数环境中输出到显示器界面。
stdin、stdout、stderr三个流的类型是: FILE * ,通常称为文件指针

C语⾔中,就是通过 FILE* 的文件指针来维护流的各种操作的

②文件指针

缓冲⽂件系统中,关键的概念是“⽂件类型指针”,简称“⽂件指针”

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

比如在VS2013编译环境提供的 stdio.h 头文件中有以下的⽂件类型申明:

struct _iobuf {
    char *_ptr;
    int _cnt;
    char *_base;
    int _flag;
    int _file;
    int _charbuf;
    int _bufsiz;
    char *_tmpfname;
};
typedef struct _iobuf FILE;

不同的C编译器的FILE类型包含的内容不完全相同,但是大同小异。每当打开⼀个文件的时候,系统会根据⽂件的情况⾃动创建⼀个FILE结构的变量,并填充其中的信息,使⽤者不必关心其细节。⼀般都是通过⼀个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。
下面创建一个FILE*的指针变量

FILE* pf;//⽂件指针变量

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

③文件的打开和关闭

文件在读写之前应该先打开文件,在使用结束之后应该关闭文件,打开文件的同时都会返回一个FILE*的指针变量指向该文件,这就相当于简历了指针和文件的关系。ANSIC规定使用fopen函数来打开文件,fclose来关闭文件。

//打开⽂件
FILE * fopen ( const char * filename, const char * mode );
//关闭⽂件
int fclose ( FILE * stream );

#include<stdio.h>
int main()
{
	FILE* pf = fopen("data.txt", "w");
	//以写的形式打开data.txt文件
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//进行文件操作


	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

④顺序读写函数介绍 

所有输⼊流⼀般指适⽤于标准输⼊流和其他输⼊流(如⽂件输⼊流);所有输出流⼀般指适⽤于标准输出流和其他输出流(如⽂件输出流)。

需要注意的是,对流进行操作的时候一定要与对应的函数就行操作,如对文件操作,对文件以读的形式打开那就只能读取文件的信息而不能向文件输出信息,同样地,如果以写的形式打开,那就只能对文件进行写操作而不能对其进行读操作,如果需要又读又写那就需要再打开文件的时候设定读写的模式。

(1)fgetc函数介绍

FILE*表示一个流,(如文件流或标准输入输出流),该函数读取流中的一个字符,当读到文件末尾或读取错误的时候会返回一个EOF。当需要将一个流的信息都读取出来可以使用这个函数一个字符一个字符的读取直至返回值为EOF(读取结束),下面将使用代码展示

代码示例:

#include<stdio.h>
int main()
{
	FILE* pf = fopen("data.txt", "r");
	//以读的形式打开data.txt文件
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//进行文件操作
	char ch = 0;
	while ((ch = fgetc(pf)) != EOF)//当fgetc返回值不为EOF就表示在没有读取失败或还没到文件末尾
	{
		printf("%c", ch);
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

其中data.txt文件(与C语言的源文件在同一个目录底下)的内容如下:

最后结果如下: 

(2) fputc函数介绍

该函数的功能是向流中写一个字符 ,如果写入成功将返回该字符,写入失败就会返回EOF。

代码示例:

#include<stdio.h>
int main()
{
	FILE* pf = fopen("data.txt", "w");
	//以读的形式打开data.txt文件
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//进行文件操作,向data.txt文件写入一个字符x
	fputc('x', pf);

	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

(3)fgets函数介绍

该函数是向流中的数据读取num个字符将其放到str这个指针所指向的空间。如果读取成功就返回str(其实就是这个字符串的地址),如果读取失败或读到文件结尾就会返回NULL。当需要将一个流的信息都读取出来可以使用这个函数一次读取num个,直至返回值为NULL(读取结束),下面将使用代码展示

代码示例:

#include<stdio.h>
int main()
{
	FILE* pf = fopen("data.txt", "r");
	//以读的形式打开data.txt文件
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	char ch[20] = { 0 };
	while (fgets(ch, 5, pf)!=NULL)//将data.txt文件的内容每次读取5个放到ch数组中,直至读取错误或文件末尾
	{
		printf("%s", ch);//将读取的
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

(4)fputs函数介绍

该函数是将str指向的内容写到流中,如果写入成功就会返回应该非0的数,如果写入失败就会返回0。

代码示例:

#include<stdio.h>
int main()
{
	FILE* pf = fopen("data.txt", "w");
	//以读的形式打开data.txt文件
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	char ch[30] = "asdfahyrhdfgqefd7890";
	fputs(ch, pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

(5)fscanf函数介绍

该函数的功能是从流中读取数据并按特定的格式存储到format这个参数里(这个参数与scanf类似)。如果在读取过程中发生读取错误或到达文件末尾,会设置相应的指示器(feof或ferror)。如果在任何数据成功读取之前发生其中之一,则返回EOF。

代码示例:

#include<stdio.h>
int main()
{
	char ch[30] = { 0 };
	FILE* pf = fopen("data.txt", "r");//以读的形式打开文件
	fscanf(pf, "%s", ch);
	printf("%s\n", ch);
	return 0;
}

 (6)fprintf函数介绍

该函数是将format所指向的字符内容输出到stream这个流中,如果发生写入错误,文件错误指示器(ferror)会被设置,同时函数通常会返回一个负数,用以表示错误的发生。如果成功的话就会返回写入流中字符的个数。

代码示例:

#include<stdio.h>
int main()
{
	char ch[30] = "12345679zxcvasdfbgre";
	FILE* pf = fopen("data.txt", "w");//以写的形式打开文件
	fprintf(pf, "%s", ch);
	printf("%s\n", ch);
	return 0;
}

 

 (7)fwrite函数介绍

该函数是将ptr所指向的size*count个字节的内容写入到流中,返回值成功写入的个数。该函数是对二进制文件进行操作的。

#include<stdio.h>
int main()
{
	char ch[30] = "12345679zxcvasdfbgre";
	FILE* pf = fopen("test", "wb");//以二进制读写的形式打开文件
	fwrite(ch,sizeof(char), sizeof(ch), pf);
	//char tmp[30] = { 0 };
	//fread(tmp, sizeof(char), sizeof(tmp), pf);
	//printf("%s\n", tmp);
	return 0;
}

(8)fread函数介绍

该函数向流中取size*count个字节的数据放入到ptr所指向的空间。返回的是读取成功的个数。可以通过每次读取一个直至返回值为0就表示读取结束或读取失败。这可以通过ferror或feof来对其进行判断,看是正常结束还是不正常结束。需要注意的是该函数是对二进制文件进行读取的

代码示例:

#include<stdio.h>
int main()
{
	//char ch[30] = "12345679zxcvasdfbgre";
	FILE* pf = fopen("test", "rb");//以二进制读写的形式打开文件
	//fwrite(ch,sizeof(char), sizeof(ch), pf);
	char tmp[30] = { 0 };
	fread(tmp, sizeof(char), sizeof(tmp), pf);
	printf("%s\n", tmp);
	return 0;
}

需要注意的是,这些函数如果对文件流进行操作时,打开文件的时候要留意是读文件还是写文件,可以从文件中读取的有fgetc,fgets,fscanf,fread函数。而将数据输出到文件中的函数有fputc,fputs,fprintf,fwrite函数。fwrite和fread只能针对文件流进行操作(还是以二进制进行操作的),而上面其余的函数是针对所以输入或输出流。

3、scanf,printf,sscanf,sprintf,fscanf,fscanf函数的区别

 (1)sscanf函数介绍

 该函数是在字符串读取格式化的数据。

代码示例:

#include<stdio.h>
int main()
{
	char str[15] = "10 1.23 avb";
	int a = 0;
	float b = 0;
	char ch[5] = { 0 };
	sscanf(str, "%d%f%s", &a, &b, ch);
	printf("%d\n", a);
	printf("%f\n", b);
	printf("%s\n", ch);
	return 0;
}

(2)sprintf函数介绍

 

该函数是把格式化的数据转化成字符串

#include<stdio.h>
int main()
{
	char str[30] = "10 1.23 avb";
	int a = 0;
	float b = 0;
	char ch[5] = { 0 };
	char tmp[30] = { 0 };
	sscanf(str, "%d%f%s", &a, &b, ch);
	sprintf(tmp, "%d %f %s", a, b, ch);
	printf("%s", tmp);
	return 0;
}

小结:scanf从标准输入流读取格式化数据,fscanf从指定的输入流上读取格式化的数据,sscanf在字符串中读取格式化的数据。printf把数据以格式化的形式打印在标准输出流上,fprintf把数据以格式化的形式输出到指定的流,sprintf把格式化的数据转化成字符串。

4、文件的随机读写

(1)fseek函数介绍

#include<stdio.h>
int main()
{
	FILE*pf=fopen("tt.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputs("This is an apple.", pf);
	fseek(pf, 9, SEEK_SET);//通过设置后两个参数,来设定光标的位置
	fputs(" sam", pf);
	char ch = 0;
	while ((ch=fgetc(pf))!=EOF)
	{
		printf("%c", ch);
	}
	fclose(pf);
	return 0;
}

 (1)ftell函数介绍

 

该函数是返回文件指针相对于于起始位置的偏移量

#include<stdio.h>

int main()
{
	FILE*pf=fopen("tt.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputs("This is an apple.", pf);
	fseek(pf, 9, SEEK_SET);
	fputs("xxx",pf);
	int ret=ftell(pf);
	printf("%ld\n", ret);//打印的是光标相对于起始的偏移量
	return 0;
}

(3)rewind

让光标回到文件的起始位置。

#include<stdio.h>

int main()
{
	FILE*pf=fopen("tt.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputs("This is an apple.", pf);
	fseek(pf, 9, SEEK_SET);
	fputs("xxx",pf);
	int ret=ftell(pf);
	printf("%ld\n", ret);//打印的是光标相对于起始的偏移量
	rewind(pf);
	ret = ftell(pf);
	printf("%ld\n", ret);//打印的是光标相对于起始的偏移量
	return 0;
}

5、文件读取结束的判定 

feof函数介绍

在文件读取过程中,不能用feof函数的返回值直接来判断文件的是否结束。feof 的作用是:当文件读取结束的时候,判断是读取结束的原因是否是:遇到文件尾结束。如果是遇到文件末尾结束的话就会返回一个非0的数,如果不是文件末尾结束的话将返回0。

ferror函数介绍

如果设置了与流关联的错误指示符,则返回一个非零值。否则,返回0。

6、文件缓冲区

ANSIC标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为
程序中每⼀个正在使用的文件开辟⼀块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓
冲区,装满缓冲区后才⼀起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小是根据C编译系统决定的。

因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。如果不刷新缓冲区或关闭文件可能会导致数据丢失等问题。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++初阶】之类和对象(中)

【C初阶】之类和对象&#xff08;中&#xff09; ✍ 类的六个默认成员函数✍ 构造函数&#x1f3c4; 为什么需要构造函数&#x1f3c4; 默认构造函数&#x1f3c4; 为什么编译器能自动调用默认构造函数&#x1f3c4; 自己写的构造函数&#x1f3c4; 构造函数的特性 ✍ 拷贝构造…

原型链-(前端面试 2024 版)

来讲一讲原型链 原型链只存在于函数之中 四个规则 1、引用类型&#xff0c;都具有对象特性&#xff0c;即可自由扩展属性。 2、引用类型&#xff0c;都有一个隐式原型 __proto__ 属性&#xff0c;属性值是一个普通的对象。 3、引用类型&#xff0c;隐式原型 __proto__ 的属…

Java官网64位下载:获取高效、安全的Java平台

Java官网64位下载&#xff1a;获取高效、安全的Java平台 Java是一种广泛应用于软件开发和跨平台应用程序的编程语言。无论是开发桌面应用程序、移动应用程序还是大型企业级系统&#xff0c;Java都是一种可靠且强大的选择。为了确保你获取到高效、安全的Java平台&#xff0c;本文…

supervision CV视觉可视化辅助工具

参考&#xff1a; https://supervision.roboflow.com/latest/ https://github.com/roboflow/supervision/tree/develop/examples 版本&#xff1a; pip install -U supervisionultralytics-8.1.35 &#xff08;大于8.1才行&#xff0c;不然可能会有错误AttributeError: ‘Res…

第5章.零、单例与小样本提示词的编写之道

零提示、单个提示和小样本提示是用于从ChatGPT中生成文本的技术。在数据匮乏或任务全新、定义模糊之时&#xff0c;我们用微妙的提示&#xff0c;让ChatGPT从无到有&#xff0c;生成文本。 面对任务&#xff0c;空无一例&#xff1a;模型凭借对任务的广泛理解&#xff0c;独辟…

贝锐蒲公英虚拟DMZ:工业设备异地组网,解决网段冲突难题

虚拟DMZ 产品/技术的原理传统DMZ&#xff1a; DMZ中文名称为“隔离区”&#xff0c;也称“非军事化区”&#xff1b;它是为解决安装防火墙后外部网络不能访问内部网络服务器的问题。网关DMZ功能开启后&#xff0c; 将内网的一台服务器完全暴露在外网&#xff08;内网某个IP绑…

在CentOS7上部署Nginx并测试指南

Nginx部署测试 Nginx简介 Nginx是俄罗斯人Igor Sysoev编写的一款高性能的HTTP和反向代理服务器。 Nginx选择了epoll和kqueue作为网络I/O模型&#xff0c;在高连接并发的情况下&#xff0c;内存、CPU等系统资源消耗非常低&#xff0c;运行稳定。 正向代理与反向代理 正向代…

Swift 周报 第四十八期

文章目录 前言新闻和社区苹果突然不造车了&#xff0c;雷军&#xff1a;非常震惊&#xff01;分析师&#xff1a;马斯克或是最大赢家你会爱上的开发者活动 提案通过的提案正在审查的提案 Swift论坛推荐博文话题讨论关于我们 前言 本期是 Swift 编辑组自主整理周报的第四十八期…

【MySQL】16.事务管理(重点) -- 2

1. 事务隔离级别 如何理解隔离性1 MySQL服务可能会同时被多个客户端进程(线程)访问&#xff0c;访问的方式以事务方式进行一个事务可能由多条SQL构成&#xff0c;也就意味着&#xff0c;任何一个事务&#xff0c;都有执行前&#xff0c;执行中&#xff0c;执行后的阶段。而所…

基于Echarts的超市销售可视化分析系统(数据+程序+论文)

本论文旨在研究Python技术和ECharts可视化技术在超市销售数据分析系统中的应用。本系统通过对超市销售数据进行分析和可视化展示&#xff0c;帮助决策层更好地了解销售情况和趋势&#xff0c;进而做出更有针对性的决策。本系统主要包括数据处理、数据可视化和系统测试三个模块。…

基于随机森林与LSTM神经网络的住宅用电比较分析及预测 代码+论文 完整毕设

摘要 本文旨在探讨基于随机森林&#xff08;Random Forest&#xff09;与长短期记忆神经网络&#xff08;Long Short-Term Memory, LSTM&#xff09;的住宅用电比较分析及预测方法。随机森林是一种集成学习方法&#xff0c;通过构建多个决策树进行预测&#xff0c;具有较强的鲁…

FL Studio21.2.3.4004音乐制作及里程碑及功能介绍

**FL Studio 21.2.3.4004&#xff1a;音乐制作的新里程碑** 随着数字音乐制作技术的不断发展&#xff0c;音乐制作软件也在不断迭代升级。今天&#xff0c;我们将聚焦于一款广受欢迎的音乐制作软件——FL Studio 21.2.3.4004&#xff0c;探讨它如何成为音乐制作领域的新里程碑…

【技巧】如何设置和解除PDF的“打开密码”?

在工作中&#xff0c;我们经常会接触到PDF文件&#xff0c;对于重要的文件&#xff0c;往往还会设置密码保护&#xff0c;那PDF的“打开密码”如何设置和解除呢&#xff1f;下面小编分享两种方法&#xff0c;一起来看看吧&#xff01; 方法一&#xff1a;使用PDF编辑器 大部分…

基于连续深度编解码器网络的医学图像鲁棒边界分割

基于连续深度编解码器网络的医学图像鲁棒边界分割 摘要引言相关工作方法-----III. PROPOSED METHOD Robust_Boundary_Segmentation_in_Medical_Images_Using_a_Consecutive_Deep_Encoder-Decoder_Network 摘要 图像分割通常用于定位目标和边界。它在许多临床应用中是必不可少的…

一步一步搭建,功能最全的权限管理系统之动态路由菜单

一、前言 这是一篇搭建权限管理系统的系列文章。 随着网络的发展&#xff0c;信息安全对应任何企业来说都越发的重要&#xff0c;而本系列文章将和大家一起一步一步搭建一个全新的权限管理系统。 说明&#xff1a;由于搭建一个全新的项目过于繁琐&#xff0c;所有作者将挑选核心…

1320亿参数,性能超LLaMA2、Grok-1!开源大模型DBRX

3月28日&#xff0c;著名数据和AI平台Databricks在官网正式开源大模型——DBRX。 DBRX是一个专家混合模型&#xff08;MoE&#xff09;有1320亿参数&#xff0c;能生成文本/代码、数学推理等&#xff0c;有基础和微调两种模型。 根据DBRX在MMLU、HumanEval和 GSM8K公布的测试…

蓝牙双模音频模块支持串口AT指令控制介绍

目录 一、BT401蓝牙音频模块简介 蓝牙音频模块支持串口AT指令控制介绍&#xff0c;这里推荐BT401蓝牙模块&#xff0c;功能简介如下&#xff1a; BT401模块是一款支持蓝牙、U盘、TF卡播放的5合1的解决方案。模组的亮点在支持无损音乐的播放&#xff0c;以及简单明了的串口控制…

婴儿专用洗衣机哪个牌子好?四大爆款婴儿洗衣机合集安利

婴儿的衣物需要特别的护理&#xff0c;因为婴儿的皮肤非常娇嫩&#xff0c;需要一个无菌&#xff0c;没有刺激性的洗涤环境&#xff0c;于是婴儿洗衣机应运而生。如果你非常注重婴儿衣物的卫生问题&#xff0c;那么婴儿洗衣机则是非常理想的选择。毕竟&#xff0c;在婴儿吃奶或…

文件上传失败原因分析与解决

图片文件上传失败 问题描述&#xff1a;在前端开发时&#xff0c;需要通过表单元素上传图片或其他文本&#xff0c;但是上传不成功&#xff0c;后端接口也没问题 html <!--onChange用来绑定数据 handleUpload用来提交数据--><form onSubmit{handleUpload}><…

Cadence HDL导出BOM并将网页数据导入Excle

【仅供个人学习记录&#xff0c;勿作他用。转载注明出处】 1. 如何导出BOM&#xff1f; 【说明】将后缀改为网页“html”&#xff0c;并勾选下面的网页。 之后就会跳出浏览器中你的BOM表就会显示。 2. 将网页BOM导入Excle&#xff1f; 不想要这个 想要这个&#xff01;&…