文件操作(1)【文件打开和关闭】【文件的顺序读写(各种函数)】【sprintf和sscanf的理解】

一.什么是文件?

在程序设计中我们一般谈的文件有两种:程序文件和数据文件

1.程序文件

程序文件是包含计算机程序代码的文件。它通常包含一系列指令和算法,用于执行特定的任务或实现特定的功能。程序文件可以由不同的编程语言编写,如C、Java、Python等。程序文件通过编译或解释等过程可以转化为计算机能够执行的机器代码。程序文件的主要作用是实现特定的算法和逻辑,控制计算机的运行。比如:源程序文件(后缀为.c),目标文件(windows环境后缀是.obj),可执行程序(Windows环境后缀为.exe)。

2.数据文件

文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。数据文件主要用于存储和组织数据。它可以包含各种类型的数据,如文本、图像、音频、视频等。数据文件通常是按照特定格式和结构进行存储的,以便于后续的读写操作和处理。数据文件的主要作用是存储和传输数据,例如数据库文件、电子表格文件、文本文件等。

3.文件名

一个文件要有一个唯一的文件表示,以便用户识别和引用。

文件包括3部分:文件路径+文件名主干+文件后缀。

例如:C:\code\test.txt,文件标识通常叫做文件名。

二.文件的打开和关闭

1.流和标准流

(1)流

我们的程序的数据需要输出到各种外部设备,也需要从外界设备获取数据,不同的外部设备输入输出操作各不相同,为了方便程序员的操作,我们就抽象出了流的概念,我们可以把流想象成流淌着字符的河。C程序针对文件,画面,键盘等数据输入输出操作都是通过流操作的。

一般情况下,当我们想要向流里写数据或者从流里读出数据,都是先打开流再操作。

(2)标准流

那为什么我们从键盘中输入数据,向屏幕上输出数据,并没有打开流呢?因为C语言程序在启动的时候就默认打开了三个流:

1.stdin—标准输入流,在大多数的环境中从键盘输入,scanf就是从标准输入流里读取数据

2.stdout—标准输出流,大多数环境中输出到显示屏界面,printf就是将信息输出到标准输出流中

3.stderr—标准错误流,大多数环境中输出到显示屏界面

默认打开了这三个流,我们使用scanf,printf等函数就可以直接进行输入输出操作的。这三个流的类型的FILE*,通常称为文件指针。

2.文件指针

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

每个被使用的文件都在内存中开辟了一个文件信息区,用来存放文件的相关信息(比如文件名,文件状态,及文件的状态),这些信息都存放在一个结构体变量中,该结构体类型是由系统声明的,取名为FILE。

当我们在打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,使用者不必关心细节。一般是通过一个FILE类型的指针来维护这个变量,这样使用起来会更加的方便。

比如:FILE* pf就是文件指针变量

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

3.文件的打开和关闭

在我们读写一个文件的时候,前提是先打开文件,在使用结束后再关闭文件。在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。

ANSI C规定使用fopen打开文件,fclose来关闭文件。

(1)fopen

有两个参数,filename就是文件名,想打开那个文件就把哪个文件名传过去,mode的意思是你打开这个文件的方式。

关于打开文件的方式有以下方式:

当我们使用w的时候如果没有文件,我们会在当前工程目录建立一个新的文件

注意:当我们打开一个文件的时候,会返回一个文件信息区的地址,所以返回值是FILE*类型,打开失败了就返回空指针。

(2)fclose

这个函数就只有一个参数,就是我们需要关闭的文件。

#include<stdio.h>
int main()
{
	FILE* p = fopen("test.txt", "r");
	if (p == NULL)
	{
		perror("fopen");
		return 1;
	}
	fclose(p);
	p = NULL;
	return 0;
}

注意:打开文件后一定要关闭,关闭后也不要忘记把指针置为空指针。

三.文件的顺序读写

这一个也是有一堆函数需要我们认识

1.fgetc和fputc

功能:字符输入输出

适用于:所有输入,输出流

(1)fputc

两个参数:一个是字符,一个是要写入的文件

#include<stdio.h>
int main()
{
	FILE* p = fopen("test.txt", "w");
	if (p == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputc('c', p);
	fputc('d', p);
	fclose(p);
	p = NULL;
	return 0;
}

这里我就成功的把c和d写入到了test.txt里面,我们也可以打开文件来看一下

(2)fgetc

这个需要配注意一下这个函数的返回值为什么是int。

1.如果成功的读取字符,返回的是字符的ASCII码值-char。

2.如果读取遇到了文件末尾,或者读取失败了,返回的是EOF(-1)。

#include<stdio.h>
int main()
{
	FILE* p = fopen("test.txt", "r");
	if (p == NULL)
	{
		perror("fopen");
		return 1;
	}
	/*fputc('c', p);
	fputc('d', p);*/
	int ch = fgetc(p);
	if (ch != EOF)
	{
		printf("%c", ch);
	}
	fclose(p);
	p = NULL;
	return 0;
}

这里我用只读的形式,成功的用fgetc把字符给打印了出来。当然如果想把所有的字符轻松的打印出来,用一个循环就可以了。

2.fputs和fgets

功能:文本行输入,输出

适用于:所有输入,输出流

(1)fputs

这个函数的用法其实跟fputc差不多,只不过fputc写入文件的是字符,fputs写入文件的是字符串。

#include<stdio.h>
int main()
{
	FILE* p = fopen("test.txt", "w");
	if (p == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputs("hello world", p);

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

其实跟fputc比就是变成了字符串。

(2)fgets

这个函数有三个参数。

关于这个函数会有几个细节需要介绍。

注意,这个num是我们需要读取的字节数。stream就是我们需要读取的文件,我们需要把从文本读取到的字符串拷贝到str里。

#include<stdio.h>
int main()
{
	FILE* p = fopen("test.txt", "r");
	if (p == NULL)
	{
		perror("fopen");
		return 1;
	}
	//fputs("hello world\n", p);
	//fputs("hello\n", p);
	char arr[10] = { 0 };
	fgets(arr, 10, p);
	printf("%s", arr);
	fclose(p);
	p = NULL;
	return 0;
}

这是文本里的字符串

打印出:hello wor

我们明明要读取的是10个字节,为什么只读出了9个字符呢?因为我们必须要给'\0'留一个字节的位置,这里的第10位个字符就是'\0'。

还有一种情况:

第一行的hello的后面还有一个'\n'当我们打印10个字符的时候这个'\n'会不会打印出来?答案是会的,这里我让大家看一下:

也就是说当我们打印的字节数多于文本里的字符数,那么这个函数也会把'\n'也给读取到。反之不会,最后还要补'\0'。

fgets函数会读取指定长度的字符,直到遇到换行符或者文件结束符为止。

fgets函数如果读取成功,则返回arr的首地址。如果这个函数读取读到了末尾或者发生了错误,则返回一个空指针。所以最好加上判断条件,再去进行下面的操作。

3.fscanf和fprintf

功能:格式化输入,输出

适用于:所有输入,输出流

(1)fprintf

fprintf函数的作用是将格式化的数据输出到指定的文件中。它与printf函数类似,但是printf函数将数据输出到标准输出流(通常是屏幕),而fprintf函数可以将数据输出到指定的文件中。

stream是一个指向文件的指针,用于指定要输出到哪个文件中。format是一个格式字符串,用于指定输出数据的格式。...表示可以传入多个参数,根据格式字符串的要求,将这些参数输出到文件中。

fprintf函数的返回值是成功输出的字符数,如果发生错误则返回负数

来看一下用法

struct S
{
	char name[20];
	int age;
	float score;
};
#include <stdio.h>
int main()
{
	struct S s = { "xioaming",18,90.0f };
    //这里我想把s里的数据存放到文本里
	FILE* pf = fopen("text.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
    //是以文本的形式写进去的
	fprintf(pf, "%s %d %f", s.name, s.age, s.score);
	fclose(pf);
	pf = NULL;
	return 0;
}

最终我们在文件中就可以看到成功的把数据写到了文本内。

(2)fscanf

上面我用fprintf把数据输出到了文本中,那么我当然也可以把这些数据给读取出来。

fscanf函数可以根据格式化字符串,从文件中读取数据,并将其按照指定的格式存储到变量中。这个函数类似于scanf函数,只不过scanf函数是从标准输入中读取数据,而fscanf函数可以从文件中读取数据。

还是上面的代码

struct S
	{
		char name[20];
		int age;
		float score;
	};
	#include <stdio.h>
	int main()
	{
		struct S s = {0};
		//我要把文件里的内容读取出来,放在变量s里面
		FILE* pf = fopen("text.txt", "r");
		if (pf == NULL)
		{
			perror("fopen");
			return 1;
		}
		//读文件
		fscanf(pf, "%s %d %f", s.name, &(s.age), &(s.score));
		//查看是否成功的读取,打印到屏幕上看看
		printf("%s %d %f", s.name, s.age, s.score);
		fclose(pf);
		pf = NULL;
		return 0;
	}

打印出来:xioaming 18 90.000000

(3)关于所有输入,输出流的理解

所有输入,输出流是包括文件流和标准流的,具体标准流的解释可以看一下上面的讲解。

那么我们在使用上面这些所有输入输出流函数的时候,我们都是针对文件流来实现从文件里读取数据还是输入数据,我们是否也可以用标准输入和标准输出流呢?

struct S
	{
		char name[20];
		int age;
		float score;
	};
	#include <stdio.h>
	int main()
	{
		struct S s = {0};
		//我要把文件里的内容读取出来,放在变量s里面
		FILE* pf = fopen("text.txt", "r");
		if (pf == NULL)
		{
			perror("fopen");
			return 1;
		}
		//读文件
		fscanf(pf, "%s %d %f", s.name, &(s.age), &(s.score));
		//这里我不用printf也能成功打印到屏幕里
		fprintf(stdout,"%s %d %f", s.name, s.age, s.score);
		fclose(pf);
		pf = NULL;
		return 0;
	}

4.fwrite和fread

功能:二进制输入输出

适用于:文件输入输出流

(1)fwrite

这个函数有四个参数。

  • ptr:指向要写入的数据的指针。
  • size:每个数据块的大小(以字节为单位)。
  • count:要写入的数据块的数量。
  • stream:指向要写入的文件的指针

fwrite函数将从指定的ptr指针处开始,将size * count个字节的数据写入到stream指针指向的文件中。它返回实际写入的数据块数量,如果返回值小于count,则表示写入文件出错或到达文件末尾。

#include <stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5 };
	FILE* pf = fopen("text.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	int sz = sizeof(arr) / sizeof(arr[0]);
	fwrite(arr, sizeof(arr[0]), sz, pf);//这里就是用二进制方式写入的
	fclose(pf);
	pf = NULL;
	return 0;
}

因为是二进制,真正要在文本文件里看,我们也看不懂。

(2)fread

  • ptr:指向用于存储读取数据的内存缓冲区的指针。
  • size:每个数据项的字节数。
  • count:要读取的数据项的个数。
  • stream:指向要读取的文件的指针。

函数返回值为实际成功读取的数据项的个数。如果返回值小于count,则可能发生了错误或到达了文件末尾。

#include <stdio.h>
int main()
{
	int arr[5] = { 0 };
	FILE* pf = fopen("text.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fread(arr, sizeof(arr[0]), 5, pf);
	int i = 0;
	for (int i = 0; i < 5; i++)
	{
		printf("%d", arr[i]);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

这个就是把二进制文件里的内容给读取的程序操作。这里也是成功的打印出来12345.

四.sprintf和sscanf

1.sprintf

str是一个指向字符数组的指针,用来存储格式化后的字符串;format是一个格式控制字符串,用来指定输出的格式;...表示可变参数,用来传入需要格式化输出的数据。

简单的说,这个函数的作用就是把格式化的数据转化成字符串,存入str里

#include <stdio.h>

int main() 
{
    char str[100];
    int num = 10;

    sprintf(str, "The number is %d.", num);
    printf("%s\n", str);

    return 0;
}

这里的str就是字符串。

2.sscanf

而这个函数跟sprintf就是反过来的。

str是要进行转换的字符串,format是转换的格式,...表示可变参数,用于接收转换后的数据。

#include <stdio.h>

int main() 
{
    char str[100];
    int num = 10;

    sprintf(str, "%d", num);
    printf("%s\n", str);//以字符串的形式打印的
    sscanf(str, "%d", &num);
    printf("%d", num);//以格式的形式打印的
    return 0;
}

其实就是一个与sprintf的逆运算。

到这里文件操作也只是进行了一部分,还有随机读写等内容,放到后面写。

感谢大家的观看,如有错误请多多指出。

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

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

相关文章

【C语言环境】Sublime中运行C语言时MinGW环境的安装

要知道&#xff0c;GCC 官网提供的 GCC 编译器是无法直接安装到 Windows 平台上的&#xff0c;如果我们想在 Windows 平台使用 GCC 编译器&#xff0c;可以安装 GCC 的移植版本。 目前适用于 Windows 平台、受欢迎的 GCC 移植版主要有 2 种&#xff0c;分别为 MinGW 和 Cygwin…

【Python】——变量名的命名规则

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

Linux shell编程学习笔记42:md5sum

0 前言 前几天在国产电脑上遇到一个问题&#xff0c;先后接到两个文件&#xff0c;如何判断这两个文件内容是否相同&#xff1f; 如果是在Windows系统&#xff0c;可以用fc命令&#xff0c;或者用我自己写的FileInfo&#xff0c;提取两个文件有MD5、SHA1、CRC32值进行比较来判…

GANs和Diffusion模型(3)

接GANs和Diffusion模型&#xff08;2&#xff09; 扩散(Diffusion)模型 生成学习三重困难(Trilemma) 指生成学习(genrative learning)的模型都需要满足三个需求&#xff1a; 高质量的采样(High Quality Samples)&#xff1a;模型应该能生成非常高质量的采样快速采样(Fast S…

使用 Python 模拟布朗运动(和股票价格)

一、说明 本文先介绍布朗运动的概念&#xff0c;紧接着应用布朗方程到股票的随机斩落模型。进而用python实现&#xff0c;并给出各种各样的条件模型。从中烘托出股票模型的规律所在。 二、什么是布朗运动&#xff1f; 布朗运动以罗伯特布朗的名字命名&#xff0c;他是第一个在通…

持续交付与持续部署相关概念(CD)

目录 一、概述 二、持续交付基本概念 2.1 持续交付的含义 2.1.1 项目管理的视角 2.1.2 产品研发的视角 2.1.3 总结 2.2 持续交付涉及的运作环境 2.2.1 开发环境 2.2.2 测试环境 2.2.3 UAT环境 2.2.4 准生产环境 2.2.5 生产环境 2.3 总结 三、持续部署基本概念 3.…

创新之路:云边对接与行业生态的前沿探索

全球 80% 的数据来自物联网&#xff0c;不论是传统行业还是新兴行业&#xff0c;都将利用更多有价值的数据来驱动业务&#xff0c;实现降本增效。智慧教育、资产追踪、环境监测、工业物联网、智慧城市、家居互联、智慧电力、智慧农业。从智能电表到智能家居&#xff0c;从机器人…

RAG:检索增强生成系统如何工作

随着大型语言模型&#xff08;LLM&#xff09;的发展&#xff0c;人工智能世界取得了巨大的飞跃。经过大量数据的训练&#xff0c;LLM可以发现语言模式和关系&#xff0c;使人工智能工具能够生成更准确、与上下文相关的响应。 但LLM也给人工智能工程师带来了新的挑战&#xff…

shopee、lazada、temu测评自养号策略解析

在跨境电商领域&#xff0c;测评作为提升销量的重要手段&#xff0c;其策略的制定和实施显得尤为重要。特别是对于Shopee和Lazada两大主流平台上的卖家而言&#xff0c;如何有效利用测评策略提升产品销量成为了一大挑战。 自养号测评系统可以批量注册买家账号、模拟真实人工操…

U8二次开发-钉钉集成

钉钉开放平台作为企业沟通和协作的重要工具,其技术的每一次迭代都为企业带来了新的机遇和挑战。随着企业对于高效沟通和智能化管理的需求日益增长,钉钉平台的SDK更新显得尤为重要。把传统的U8与钉钉平台集成,可以有效的将业务功能和角色进行前移,打破应用系统二八原则,即8…

Vue(十二):脚手架配置代理,github案例,插槽

一、脚手架配置代理 老师讲的主要有两种方法&#xff1a; 但是我的没有proxy&#xff0c;只有proxyTable,之前一直不成功&#xff0c;现在我是这样配置的&#xff1a; config文件夹下的index.js: App.vue: 然后就成功了&#xff1a;&#xff08;我真服了&#xff0c;之前在这…

Linux中xz一次恶意后门处理的名场面-尚文网络xUP楠哥

进Q群11372462领取专属报名福利! 说在前面 Linux系统中所使用的xz软件是用于日常文件的归档压缩工具&#xff0c;据悉就在今日&#xff0c;Utils 5.6.0、5.6.1版本存在恶意后门植入漏洞&#xff08;CVE-2024-3094&#xff09;。开发人员在调查SSH性能问题时发现了涉及XZ Util…

Taro多行文本最多展示5行,超出“查看更多”展示,点击弹层

Taro中&#xff0c;页面需求&#xff1a; 多行文本&#xff0c;展示最多展示5行&#xff0c;超出5行&#xff0c;展示“查看更多”按钮&#xff0c;点击弹层展示文本详细信息。 弹层代码就不说了&#xff0c;着重说一下怎么获取区域高度&#xff5e; 1.区域设置max-height&am…

2_2.Linux中的远程登录服务

# 一.Openssh的功能 # 1.sshd服务的用途# #作用&#xff1a;可以实现通过网络在远程主机中开启安全shell的操作 Secure SHell >ssh ##客户端 Secure SHell daemon >sshd ##服务端 2.安装包# openssh-server 3.主配置文件# /etc/ssh/sshd_conf 4.…

嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记12:DAC数模转换

系列文章目录 嵌入式|蓝桥杯STM32G431&#xff08;HAL库开发&#xff09;——CT117E学习笔记01&#xff1a;赛事介绍与硬件平台 嵌入式|蓝桥杯STM32G431&#xff08;HAL库开发&#xff09;——CT117E学习笔记02&#xff1a;开发环境安装 嵌入式|蓝桥杯STM32G431&#xff08;…

Php_Code_challenge12

题目&#xff1a; 答案&#xff1a; 解析&#xff1a; 字符串拼接。

iPhone设备中调试应用程序崩溃日志的高效方法探究

​ 目录 如何在iPhone设备中查看崩溃日志 摘要 引言 导致iPhone设备崩溃的主要原因是什么&#xff1f; 使用克魔助手查看iPhone设备中的崩溃日志 奔溃日志分析 总结 摘要 本文介绍了如何在iPhone设备中查看崩溃日志&#xff0c;以便调查崩溃的原因。我们将展示三种不同的…

Windows 上路由、端口转发配置,跨网络地址段

一、背景 有时候我们会遇到这样的场景&#xff0c;一批同一局域网中只有某一台主机带外且系统为windows&#xff0c;局域网中其他非带外的主机要想访问外网&#xff0c;本文将介绍如何配置在带外主机上开启路由及端口转发。 二、配置操作 2.1、带外主机开启路由转发 1&#x…

Centos7.X服务器搭建VOS系统的REC录音转换MP3,并支持外呼系统wav转换MP3

由于有的公司客户需要自己下载录音或做话务质检等工作需要&#xff0c;需要从VOS系统中把录音下载到其它服务器使用&#xff0c;但是VOS录音格式是REC格式的&#xff0c;就算下载下来了也无法直接播放&#xff0c;因此我们需要搭建一台转换MP3的服务器来完成需求&#xff01; 外…

15-研发流程实战:IAM项目是如何进行研发流程管理的?

为了向你演示流程&#xff0c;这里先假设一个场景。我们有一个需求&#xff1a;给IAM客户端工具iamctl增加一个helloworld命令&#xff0c;该命令向终端打印hello world。 开发阶段 开发阶段是开发者的主战场&#xff0c; 它又可分为代码开发和代码提交两个子阶段。 代码开发…