C语言文件操作详解(包含文件读写操作解析)(1)

一、 为什么使用文件?

如果没有文件,那么我们写的程序是存储会在电脑的内存中的,此时我们若是退出程序,那么内存收回,程序的相关数据就丢失了;等到下次再次运行程序,是看不到上次程序的数据的。文件的作用就是将数据进行持久化的保存。


二、什么是文件?

在磁盘(硬盘)上的一些存储数据的存储形式的具象化就是文件。

在程序设计中,我们一般的文件有两种:程序文件和数据文件(按照文件功能来分的)

1.程序文件

程序文件包括源程序文件(后缀为.c)、目标文件(windows环境后缀是.obj)、可执行程序文件(windows环境后缀是.exe)

2.数据文件

数据文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。

这里我们讨论的是数据文件,一般我们写代码时所处理的数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显示器上。而有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使用,这里处理的就是磁盘上的文件。

3.文件名

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

文件名包含三部分:文件路径+文件主干名+文件后缀。

例如:c:\code\test\.txt

为了方便起见,文件标识常常被称为文件名

注意有时候文件并没有后缀。


三、二进制文件和文本文件

根据数据的组织形式,数据文件被称为文本文件或者是二进制文件。

数据再内存中以二进制的形式存储,如果不加转换的输出到外村的文件中,就是二进制文件。

如果要求再外存上以ASCLL码形式存储,则需要再存储之前转换。以ASCLL字符的形式存储的文件就是文本文件。


四、文件的打开和关闭

1.流和标准流

我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输入输出操作方式各不相同,为了方便程序员对各种设备进行方便的操作,我们抽象出了流的概念,我们可以把流想象成流淌着许多字符的河流。

C语言程序针对文件、画面、键盘的数据输入输出操作都是通过流进行操作的;

一般情况下,我们想要向流里面写数据,或者从流中读取数据,都要先打开流。然后操作。

标准流

此时可能会有疑问,我们在平时写代码的时候,为什么没有打开流的具体操作呢,而是直接写代码呢?那是因为C语言程序在启动的时候,默认打开了3个流:

#stdin-标准输入流,在大多数环境中从键盘输入,scanf函数就是从标准输入流中读取数据。

#stdout-标准输出流,大多数环境中输出到显示器界面,printf函数就是将信息输出到标准输出流中。

#stderr-标准错误流,大多数环境中输出到显示器界面,

这是默认打开的三个标准流,我们使用scanf、printf等函数就可以直接进行输入输出操作。

而它们的类型是:FILE*(通常被称为文件指针)

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

2.文件指针

每个被使用的我呢见都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(例如文件名称、文件状态以及文件当前的位置等)。而这些信息是保存咋一个结构体变量中的。而这个结构体类型由系统固定声明。取名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;

不同的编译器的FILE类型的结构体包含的内容并是大同小异的,不是完全相同的;

每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并且填充相应的信息,在这里读者不需要过多关系,只需要明白,FILE*的结构体中包含了一个文件的相关信息。一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便;

例如

FILE* pf;

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

3.文件的打开和关闭具体实现

我们要操作文件就要先打开文件,结束时就要关闭文件(就如同喝水,要先打开瓶盖,不喝了自然就要扭紧瓶盖)

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

 mode表示文件打开的模式,文件的打开模式有很多:

文件使用方式含义如果指定文件不存在
“r”(只读)为了输入数据,打开一个已经存在的文本文件出错
“w”(只写)为了输出数据,打开一个文本文件建立一个新的文件
“a”(追加)

向文本文件尾添加数据

建立一个新的文件
“rb”(只读)为了输出数据,打开一个二进制文件出错
“wb”(只写)为了输出数据,打开一个二进制文件建立一个新的文件
“ab”(追加)向二进制文件尾添加数据建立一个新的文件
“r+”(读写)为了读和写,打开一个文本文件出错
“w+”(读写)为了读和写,打开一个文本文件建立一个新的文件
“a+”(读写)打开一个文件,向文件尾进行读写建立一个新的文件
“rb+”(读写)为了读和写打开一个二进制文件出错
“wb+”(读写)为了读和写,建立一个新的二进制文件建立一个新的文件
“ab+”打开一个二进制文件,在我呢见尾进行读和写建立一个新的文件

在这里我们主要使用其中几种打开模式;

现在我们通过一个例子来先简单地看一下是怎么样操作的 

这副截图是未进行文件操作之前(Ctrl+o在VS里面快捷打开文件)

#include<stdio.h>
int main()
{
	FILE* pf = fopen("crea.txt", "w");
	//此部分在介绍文件的顺序读写之后会有相应的代码补充,这也是文件操作的主体部分
	fclose(pf);
	return 0;
}

 现在我们进行文件的只写,那么按照上述表格它会自动创建一个文件

进行只写之后:

可以发现,它自动生成了一个crea文本文件,那么使用“r”一类的模式的时候必须要存在要被进行操作的文件,不然会出错(其实可以这样理解,想要读取文件,首先你得存在文件,否则到哪里读取呢?相反,想要写一个文件,在没有那个文件的时候系统可以给你创建一个文件,因为反正文件的内容是人为输入的,这并不影响操作的进行) 


五、文件的顺序读写

文件的顺序读写使用的函数就是我们进行文件操作的主体部分,顺序读写就是读一个或者写一个,文件里面的光标就往后移动一个,就是按照顺序来进行操作;

我们先来简单了解一下相关的顺序读写的函数

函数名功能适用于
fgetc字符输入函数所有输入流
fputc字符输出函数所有输出流
fgets文本行输入函数

所有输入流

fputs文本行输出函数所有输出流
fscanf格式化输入函数所有输入流
fpringf格式化输出函数所有输出流
fread二进制输入函数文件
fwrite二进制输出函数文件

上面表格中说到的所有输入流一般指的是包含了标准输入流和 其他输入流(例如文件输入流)的流;

所有输出流指包含了标准输出流和其他输出流(例如文件输入流)的流。

输入输出可以这样理解:在我们一般写代码的时候我们可以把包含着代码的程序看作一个对象,把显示器看作一个对象,我们输出就是输出到显示器那个对象上,输入就是输入到程序这个对象上;

此时对于文件来说就是把显示器换成了文件,我们进行读的时候就是把文件的内容输入到程序中,这时候我们程序就相当于多包含了一部分数据(文件中的数据),若是可以打印,我们在程序中可以打印出来,而进行写文件的时候,程序中写的代码就要被输出到从文件中了

具体代码实现:

1.fgetc和fputc

fgetc是对文件进行读取操作,即从文件中一次读取一个字符放在程序代码中;fputc是把程序代码上的一个字符输出到文件中

#include<stdio.h>
#include<errno.h>

int main()
{
	FILE* pf = fopen("test.txt", "w");//首先以写文件的方式创建一个文件
	if (pf == NULL)
	{
		perror("fopen");
		return 1;//打开失败就终止
	}
	int C = 'a';
	for (C = 'a'; C <= 'z'; C++)
	{
		fputc(C, pf);
	}

	fclose(pf);
	return 0;
}

 未报错

 来看我们写的文件

写了一个文件之后,我们就可以从这个文件里面读取数据了;


int main()
{
	FILE* pf = fopen("test.txt", "r");//以读的方式来打开一个文件
	if (pf == NULL)
	{
		perror(pf);
		return 1;
	}
	char ret;
	while (( ret = fgetc(pf)) != EOF)//,读一个光标就移动到下一个字符位置,遍历读取
	{
		printf("%c", ret);
	}
	fclose(pf);
	return 0;
}

2.fgets和fputs

对比fgetc和fputc我们可以知道现在要介绍的两个函数都是对于文本行进行操作的

int main()
{
	FILE* pf = fopen("test2.txt", "w");
	if (pf == NULL)
	{
		perror(pf);
		return 1;
	}
	const char* str = "abcdefg";
	fputs(str, pf);
	fclose(pf);
	return 0;
}


int main()
{
	char ret[10];
	FILE* pf = fopen("test2.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	fgets(ret, 4, pf);
	printf("%s", ret);
	fclose(pf);
	return 0;
}

 

fgets是从pf文件流里面拿取数据,拿取多少个取决于中间那个数字参数,但是实际上放到第一个参数也就是数组里面的比你输入的数值少一个,最后一个是'\0'字符;

这是调试过程可以窥见数组中的具体数据;


接下来还有许多内容见文件操作(2) !!

  • 58
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与国已互相成为双方最大的交易伙伴。国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占国外贸总值的15.4%。在过去20余年,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值