c语言 文件与文件操作

🏠 一.引言 

    我们日常生活中会将我们制作的ppt,word等存放在文件里进行归类,你是否知道我们能用cC语言对文件进行操作呢(比如文件的打开,关闭和读写等)?那接下来跟博主一起来学习下吧。

🏠二.什么是文件

   磁盘上的文件就是文件,可以理解为一个信息集合体。我们一般根据文件的功能将其分为两类:一类是程序文件,一类是数据文件。

  ◕‿◕文件名

 文件名相当于是一个标志,⼀个⽂件要有⼀个唯⼀的⽂件标识,以便⽤⼾识别和引⽤。

⽂件名包含3部分: ⽂件路径+⽂件名主⼲+⽂件后缀 。 比如: c:\code\test.txt

小补充:1.文件名可以不包含后缀名,比如.txt文件类型,显示文件扩展名就可以看到

               2.文件名后缀表示文件的默认打开方式

               3.文件名有一些非法字符,如\ / : * ? " < > |

1.程序文件

      程序文件包括源程序⽂件(后缀为.c),⽬标⽂件(windows环境后缀为.obj),可执⾏程序(windows环境后缀为.exe)。

2.数据文件

   ⽂件的内容不⼀定是程序,⽽是程序运⾏时读写的数据,⽐如程序运⾏需要从中读取数据的⽂件,或者输出内容的⽂件。

 数据文件分类

数据文件按数据的组织形式,一般分为二进制文件和文本文件。数据在内存中以⼆进制的形式存储,如果不加转换的输出到外存,就是⼆进制⽂件。如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的⽂件就是⽂本⽂件。

🏠三.对文件的操作

    类比我们平时喝汽水我们常规步骤是打开瓶子,喝汽水,最后再关闭瓶子。类似地,我们对文件的操作首先是要打开文件,对文件进行输入或输出,最后再关闭文件。我们先来细🔒打开文件和关闭文件。

   在介绍打开与关闭文件之前,我们先来普及一个概念叫做流。

1.流

   流的源来:我们对一个文件可以将他输入屏幕/另一个文件等等不同的设备,这个时候不同设备对你的要求不同。好比一个工厂,我们需要多条生产线,一条分装这种产品,另一条分装那一种产品....我们的流就好比一条生产线分出的多个岔口这些岔口指向不同设备。

  C程序针对⽂件、画⾯、键盘等的数据输⼊输出操作都是通过流操作的.⼀般情况下,我们要想向流⾥写数据,或者从流中读取数据,都是要打开流,然后操作。

1.1标准流

那为什么我们从键盘输⼊数据,向屏幕上输出数据,并没有打开流呢?那是因为C语⾔程序在启动的时候,默认打开了3个流:
stdin - 标准输⼊流,在⼤多数的环境中从键盘输⼊,scanf函数就是从标准输⼊流中读取数据。
stdout - 标准输出流,⼤多数的环境中输出⾄显⽰器界⾯,printf函数就是将信息输出到标准输出
流中。
stderr - 标准错误流,⼤多数环境中输出到显⽰器界⾯。
这是默认打开了这三个流,我们使⽤scanf、printf等函数就可以直接进⾏输⼊输出操作的。
更具体点,我们可以知道流被定义为指针( 更多地理解为在流中操作的工具),指针就是地址,我们可以通过地址(流)找到这个我们所要的设备。以上三种流都是 FILE*类型的指针, 通常称为 ⽂件指针 C语⾔中,就是通过 FILE* 的⽂件指针来维护流的各种操作的。

1.2文件指针

每个被使⽤的⽂件都在内存中开辟了⼀个相应的 ⽂件信息区 ,⽤来 存放⽂件的相关信息 (如⽂件的名 字,⽂件状态及⽂件当前的位置等)。这些信息是保存在⼀个结构体变量中的。该结构体类型是由系统声明的,取名 FILE.
struct _iobuf {
 char *_ptr;
 int _cnt;
 char *_base;
 int _flag;
 int _file;
 int _charbuf;
 int _bufsiz;
 char *_tmpfname;
 };
typedef struct _iobuf FILE;
每当打开⼀个⽂件的时候,系统会根据⽂件的情况⾃动创建⼀个FILE结构的变量,并填充其中的信
息, 一般是用一个FILE*指针来维护它的。 定义pf是⼀个 指向FILE类型数据的指针变量 。可以使pf指向某个⽂件的 ⽂件信息区 (是⼀个结构体变 量)。 通过该⽂件信息区中的信息就能够访问该⽂件。 也就是说,通过⽂件指针变量能够间接找到与 它关联的⽂件。

2.文件的打开与关闭

 基于之前的理解,我们是用一个文件指针来对文件进行间接维护和操作,所以我们可以推出FILE*类型指针是我们对文件进行读写等操作所必备的,因此我们就可以理解fopen的工作原理了

fopen  这是用来打开文件的函数原型如下

这下应该知道为什么会返回一个FILE*类型的指针了吧。
fclose 这个函数用来关闭文件
注意: 1.使用fopen如果文件打开失败,会返回个空指针,这时他就是一个空指针,我们需要检测             下。
            2.fclose能力是关闭文件,但不能置指针为空指针,我们应该手动置为空。
int main()
{

	FILE* pf=fopen("data.txt","w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

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

文件打开后我们当然要用比如进行读写,fopen第二个参数就是打开方式

注意:对于一个没有存在的文件直接进行读会报错

3.文件的顺序读写

  

我们知道文件里内容是有光标的,顺序读写就指的是这个光标一直往后推进

一些顺序顺序读写函数

注意:fread和fwrite只适用于文件流

3.1fgetc和fputc

从函数名可以看出putc是放一个字符,getc是读一个字符

3.2 fgets和fputs函数

注意:fgets是从流中读取num-1个字符因为还要给\0留位

int main()
{
	FILE* pf = fopen("data2.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	/*char arr[20] = "abcdef";
	fputs(arr, pf);*/
	char name[20] = "xxxxxxxxxxxx";
	fgets(name, 7, pf);
	printf("%s\n",name);

	fclose(pf);
	pf = NULL;

	return 0;
}

3.3 fscanf和fprintf函数

struct S
{
	char name[20];
	int age;
	float score;
};

int main8()
{
	struct S s = { 0 };
	FILE* pf = fopen("dataa.txt", "r");
	//打开文件
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读文件  注意取址符&
	fscanf(pf, "%s %d %f", s.name, &(s.age), &(s.score));
	//读pf中数据到结构体
	//写入
	fprintf(stdout, "%s %d %.1f\n", s.name, s.age, s.score);
	//将结构体写入到标准输出流
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

3.4 fwrite和fread

  这两个文字是针对二进制文件的,也就是他的读写都是针对二进制。

struct S
{
	char name[20];
	int age;
	float score;

};
int main()
{
	struct S s = { "zhangsan",18,99.6 };
	FILE* pf = fopen("dataa1.txt", "wb");//二进制写入
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fwrite(&s, sizeof(s), 1, pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

4.文件的随机读写

我们前面知道顺序指的是光标,那我们能不能让光标随便动读写我们想要的呢?这时就要用到我们的随机读写函数。随机指的是你指哪打哪

4.1 fseek函数

fseek是根据根据⽂件指针的位置和偏移量来定位⽂件指针

4.2  ftell

ftell函数返回⽂件指针相对于起始位置的偏移量,以便我们进行调整

4.3 rewind

当我们不知道光标在哪想从头来过就可以用rewind让⽂件指针的位置回到⽂件的起始位置

int main2()
{

	FILE* pf = fopen("data2.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	int ch = 0;
	ch = fgetc(pf);
	printf("%c\n", ch);

	ch = fgetc(pf);
	printf("%c\n", ch);

	ch = fgetc(pf);
	printf("%c\n", ch);

	//fseek(pf, -3, SEEK_CUR);   从当前位置
 	//fseek(pf, 3, SEEK_SET);    从开头
	fseek(pf, -4, SEEK_END);  // 从末尾
	ch = fgetc(pf);
	printf("%c\n", ch);

	long size = 0;
	size = ftell(pf);//返回现在光标距起始位置的偏移量
	printf("当前偏移量离起始位置为%ld\n", size);

	rewind(pf);//使光标回到开头
	ch = fgetc(pf);
	printf("%c\n", ch);

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

🏠四.文件读取结束的判定

1. ⽂本⽂件读取是否结束,判断返回值是否为 EOF fgetc ),或者 NULL fgets
例如:
fgetc 判断是否为 EOF .
fgets 判断返回值是否为 NULL .
2. ⼆进制⽂件的读取结束判断,判断返回值是否⼩于实际要读的个数。
fread判断返回值是否⼩于实际要读的个数.
被错误使用的feof和ferror
1.   feof
牢记:在⽂件读取过程中,不能⽤feof函数的返回值直接来判断⽂件的是否结束。
feof 的作⽤是:当⽂件读取结束的时候, 判断是读取结束的原因是否是:遇到⽂件尾结束

2.ferror

他的作用是判断在文件读取结束后,是否因为遇到错误而结束

好了本次分享结束啦,喜欢的话给博主来个三连吧~๑ᵒᯅᵒ๑

评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值