c语言 文件与文件操作

发布时间:2023年12月18日

🏠 一.引言?

? ? 我们日常生活中会将我们制作的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

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

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

文章来源:https://blog.csdn.net/2301_79448270/article/details/135045012
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。