C语言中常用的文件操作

news2024/9/26 16:40:47

本文将介绍常用的关于文件操作函数,如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语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。如果不刷新缓冲区或关闭文件可能会导致数据丢失等问题。

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

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

相关文章

解决VMWare Esxi 6.5.0 导出虚拟机时发生网络错误

解决办法&#xff1a;使用vmware ovftool工具导出。 1 先安装该工具到windows下面&#xff0c;有32位的和64位的 2 用管理员进入命令方式&#xff1a; 进入&#xff1a;c:\windows 进入工具命令当前文件夹&#xff08;具体看用户的安装路径&#xff09;&#xff1a; cd \p…

【深度解读】出海社交软件云安全战略:关键技术与实践路径

随着中国社交软件企业扬帆出海&#xff0c;面对全球市场的机遇与挑战&#xff0c;确保云环境下的信息安全与合规成为了企业能否成功立足的关键要素。尤其在社交领域&#xff0c;用户数据隐私保护、严格遵守各国法律法规以及防范高级网络攻击的压力日益增大。以下将从技术架构、…

vue3封装Element动态表单组件

1. 封装组件DymanicForm.vue 使用component实现动态组件组件不能直接使用字符串传入&#xff0c;所以根据传入的组件名称找到对应的组件校验规则&#xff0c;可使用rule传入自定义规则&#xff0c;也可以使用封装好的基本规则 示例中使用了checkRequired暴露重置方法和校验方法…

git配置密钥

要配置 Git 密钥&#xff0c;可以按照以下步骤进行操作&#xff1a; 1.生成密钥&#xff1a;首先&#xff0c;在终端或命令提示符中运行以下命令生成密钥对&#xff1a; ssh-keygen -t rsa -b 4096 -C "dengweng-pulse.net"这将生成一个 RSA 密钥对&#xff0c;其中…

面试题:Java虚拟机JVM的组成

1. 基础概念 JVM是什么 Java Virtual Machine Java程序的运行环境&#xff08;java二进制字节码的运行环境&#xff09; 好处&#xff1a; 一次编写&#xff0c;到处运行 自动内存管理&#xff0c;垃圾回收机制 JVM由哪些部分组成&#xff0c;运行流程是什么&#xff1f; …

vue.js——学习计划表

1&#xff09;准备工作 ①打开D:\vue\chapter02\ learning_schedule 目录&#xff0c;找到 index.html 文件。 在文件中引 入BootStrap 样式文件&#xff0c;具体代码如下 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8&qu…

tensorflow安装GPU版报错cublasLt64_11.dll缺失

我的报错是&#xff1a; Use tf.config.list_physical_devices(GPU) instead. 2024-03-28 17:01:46.724677: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the follo…

蓝桥杯嵌入式学习笔记(6):IIC程序设计

目录 前言 1. IIC基本原理 2. 电路原理 3. 代码编程 3.1 预备工作 3.2 AT24C02写读功能编写 3.2.1 AT24C02写操作实现 3.2.2 AT24C02读操作实现 3.3 MCP4017写读功能编写 3.3.1 MCP4017写操作实现 3.3.2 MCP4017读操作实现 3.4 main.c编写 3.4.1 头文件引用 3.4.…

react-navigation:

我的仓库地址&#xff1a;https://gitee.com/ruanjianbianjing/bj-hybrid react-navigation&#xff1a; 学习文档&#xff1a;https://reactnavigation.org 安装核心包: npm install react-navigation/native 安装react-navigation/native本身依赖的相关包: react-nativ…

水电站生态流量监测解决方案:亲历水电站生态监控改造

​记得那是在2022年夏天,我所在的环保咨询公司接到了一项非常具有挑战性的监测项目。某省的环保部门要求对辖区内所有水电站的生态流量情况进行评估,并给出整改建议。作为项目负责人,我深知这项工作的重要意义。&#xff08;选自&#xff1a;智慧水务数字孪生安全监测解决方案提…

武汉星起航公司助力零经验新手卖家征战亚马逊跨境电商市场

在数字化浪潮的推动下&#xff0c;亚马逊跨境电商行业正逐渐成为众多创业者和企业家们的新战场。然而&#xff0c;对于零经验的新手卖家而言&#xff0c;这片广袤的电商海洋无疑充满了未知与挑战。在这个关键时刻&#xff0c;武汉星起航公司以其专业的服务和深厚的行业积累&…

怎么做扫描二维码填写数据?用二维码收集用户反馈的方法

现在很多人都开始使用扫码填表的方式来收集用户反馈、签到登记、问卷调查等类型的用途&#xff0c;这种方式的使用不仅减少了制作者的成本压力&#xff0c;采用无纸化登记也提高了用户填写数据的便利性。只需要制作一个二维码&#xff0c;分享之后就可以让许多人同时扫码填写数…

详解GPT模型的前世今生

省流版&#xff1a; GPT模型是一种基于神经网络的自回归语言模型。该模型使用了一个称为“Transformer”的架构&#xff0c;从而有效避免了传统的循环神经网络产生的梯度消失问题。从第一代GPT到现在的GPT4&#xff0c;没带都产生了不同的变化&#xff0c;其性能也越来越强大。…

【Java扫盲篇】String、String Buffer和String Builder的区别

你在面试时&#xff0c;面试官让你讲讲String String Buffer String Builder的区别&#xff0c;你是否能流畅的、完整的叙述出他们三者的区别? ✍先说结论 相同点&#xff1a; 他们的底层都是由char数组实现的。不同点&#xff1a; String对象一旦创建&#xff0c;是不能修…

android安卓餐厅点餐课设

一、引言 随着移动互联网的快速发展&#xff0c;手机应用已经成为我们日常生活中不可或缺的一部分。餐饮行业也积极借助移动应用的力量&#xff0c;提供更便捷、高效的点餐服务。本文将介绍一个基于安卓系统开发的餐厅点餐APP的课程设计项目&#xff0c;探讨其设计理念、功能特…

PostgreSQL数据库如何新建登录用户?

在PostgreSQL数据库中&#xff0c;如何创建新的登录用户呢&#xff1f; 默认情况&#xff0c;PostgreSQL数据库的默认用户是&#xff1a;postgres &#xff0c;如果我们需要创建一个新的低权限用户角色&#xff0c;应该如何操作&#xff1f;本章教程&#xff0c;简单介绍一下这…

JavaFX的安装和使用

JavaFX的安装 安装可以参考&#xff1a;IDEA安装JavaFx_idea2019 javafx 下载安装-CSDN博客 JavaFX的使用 在JavaFX中&#xff0c;类的成员函数和操作本身被模式化作为在目标类中的类&#xff0c;而参数和返回值被表示为属性。代表目标对象的属性名是“this”。代表返回值的…

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

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

经纬恒润RTaW-Pegase:车载网络通信建模与时间特性分析工具

▎RTaW简介 RTaW-Pegase是由法国国家信息与自动化研究所&#xff08;INRIA&#xff09;旗下的RTaW公司开发的产品。它主要用于构建和优化汽车、航空航天以及工业领域的通信网络&#xff0c;包括时间敏感网络&#xff08;TSN&#xff09;、CAN&#xff08;FD&#xff0c;XL&…

【系统架构师】-第12章-信息系统架构

信息系统架构(ISA)是指对某一特定内容里的信息进行统筹、规划、设计、安排等一系列有机处理的活动。 为了更好地理解信息系统架构的定义&#xff0c; 特作如下说明: (1)架构是对系统的抽象&#xff0c;它通过描述元素、元素的外部可见属性及元素之间的关系来反映这种抽象。因此…