C语言:文件操作

1.文件基本概念

我们一般写程序是将数据存储到电脑的内存中,当程序退出时,内存回收,数据就丢失了,为了让数据永久保存,我们需要使用文件

1.1 什么是文件

磁盘上的文件就是文件
比如:在这里插入图片描述
在程序设计中,我们将文件分为两类:程序文件和数据文件

1.2 程序文件

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

1.3 数据文件

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

1.4 文件名

一个文件有且只有唯一的文件名与之对应
文件名包括:文件路径 + 文件名主干 + 文件后缀
例如:D:\C-code\2024_3_16_文件操作\2024_3_16_文件操作\myfile.txt
其中
文件路径:D:\C-code\2024_3_16_文件操作\2024_3_16_文件操作
文件主干名:myfile
文件后缀:.txt
**.**表示当前目录
**. .**表示上级目录

2.流

我们程序需要与不同的外设进行交流,而与不同的外设进行交流时的方法又不一样,如果每次都有一种特定的方法才能使数据写入外设,那太麻烦了,所以C语言使用了流的概念。
比如,显示屏和文件就是两个不同的外设,当我们将数据显示在屏幕上时,就需要标准输出流”stdout“,而当我们需要将数据写入到文件中就会使用输出流”Output Stream“,
简单来说:文件流就像一条流动的河流,而这条河流中的水流就是文件中的数据。当你要读取文件时,就仿佛在这条河流的上游取水;当你要写入文件时,就仿佛在这条河流的下游放水。文件流的概念就是为了简化文件操作,让你不需要关心文件在磁盘上的具体存储细节。你只需要将文件看作一个可以流动的数据流,然后像操作水管一样来操作文件流,就可以方便地进行数据的读取和写入。

3.文件指针

文件指针是一个指向文件的指针,它用于在程序中操作文件。文件指针是一个特殊的变量,它存储了文件在内存中的地址信息,通过这个地址,程序可以访问和操作文件。
简单来说,当我们使用fopen函数打开一个文件时,fopen函数会返回一个FILE类型的指针,我们可以使用FILE * 类型的指针变量来接收这个变量,这样就可以通过这个指针访问文件并操作文件了

4.文件的打开和关闭

文件在读写之前应该先打开文件,当使用完毕后应该关闭文件。
在编写程序的时候,在打开文件的同时,都会返回⼀个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。

//打开⽂件
FILE * fopen ( const char * filename, const char * mode );
//filename文件名, mode:打开方式
//关闭⽂件
int fclose ( FILE * stream );
//stream:文件指针变量

其中的mode有多种模式:
在这里插入图片描述
其中:
r

  • 该文件已经存在
  • 文件中有数据
  • 可以查看该数据
  • 不能写如数据

w

  • 可以不存在该文件,直接创建
  • 可以写入数据
  • 不能查看数据
  • 如果该文件中有数据,那么会被覆盖

混淆
输入操作对应的是读操作(r), 不能写入文件
输出操作对应的是写操作(w),不能读入文件

用输入操作为例,好像可以输入,可以读,不能写入,这几个字眼互相矛盾了。
其实,这里的输入不是我们理解的像从键盘上输入数据的那种输入,而是从文件中读取数据到程序中,这个操作被称为输入操作(读操作)
从文件到程序是一个输入过程。

—————————————————————————————
演示打开文件

int main() {
	FILE* pf = fopen("myfile.txt", "");
	if (pf == NULL) {
		perror("myfile.txt");
		return;
	}
	fclose(pf);
	pf = NULL;

	return 0;
}

创建了一个文件myfile.txt
在这里插入图片描述
里面没有数据

在使用r进行读操作时没有文件会报错

int main() {
	FILE* pf = fopen("aa.txt", "r");
	if (pf == NULL) {
		perror("fopen");
		return;
	}
	fclose(pf);
	pf = NULL;

	return 0;
}

这里我没有创建aa.txt
在这里插入图片描述

5.文件的顺序读写

在这里插入图片描述

5.1 fgetc和fputc

int fputc ( int character, FILE * stream );
int fgetc ( FILE * stream );

这两个函数都用于读入和输入单个字符

int main() {
	FILE* pf = fopen("myfile.txt", "w");
	if (pf == NULL) {
		perror("fopen");
		return;
	}
	//pf为文件指针,说明将这几个字符输入到文件中去了
	/*fputc('a', pf);
	fputc('b', pf);
	fputc('c', pf);
	fputc('d', pf);
	fputc('f', pf);*/
	//stdout,标准输出流,直接输出到屏幕上,那么在文件中就不会由任何数据了
	fputc('e', stdout);
	fputc('b', stdout);
	fputc('c', stdout);
	fputc('d', stdout);
	fputc('f', stdout);

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

fputc(‘e’, stdout);
将e输出到屏幕上
fputc(‘b’, pf);
将b放入文件中

—————————————————————————————
现在先在文件myfile中输入一些字符:
在这里插入图片描述
用fgetc函数及将数据从文件读入到程序中

int main() {
	FILE* pf = fopen("myfile.txt", "r");//myfile文件已经创建,并在里面输入了数据

	if (pf == NULL) {//检查pf是否为空
		perror("fopen");
		return;
	}

	printf("%c", fgetc(pf));

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

在这里插入图片描述

5.2 fgets

fgets用于从指定的流中读取一行数据,直到达到指定的最大字符数,或者遇到换行符或EOF(文件结束标志)。

char * fgets ( char * str, int num, FILE * stream );
//str为接受数据的地址

参数解释:

  • str:这是指向一个字符数组的指针,fgets将把读取到的字符串放入这个数组。
  • n:这是要读取的最大字符数(包括空字符’\0’)。
  • stream:这是要读取的输入流。

函数返回值:

  • 如果成功,该函数返回相同的str参数。
  • 如果到达文件末尾或者没有读取到任何字符,str的内容保持不变,并返回一个空指针。
  • 如果发生错误,也返回一个空指针。
int main() {
	FILE* pf = fopen("myfile.txt", "r");//只读操作
	if (pf == NULL) {
		perror("fopen");
		return;
	}
	

	//输出字符串
	char c[25];
	fgets(c, 25, pf);
	printf("%s", c);
	//fgets函数的第二个参数必须要知道需要读取多少个字符,不方便
	//使用fgets循环求得文件中字符的数量
	//char num[100];
	//int count = 0;

	//while (fgets(num, sizeof(num), pf )) {
	//	count += strlen(num);
	//}
	//rewind(pf);//重置文件指针到开头
	printf("%d", count);
	//char* ret = (char*)malloc(count+1);//留一个位置fang\0
	//if (ret == NULL) {
	//	perror("malloc");
	//	fclose(pf);
	//	return;
	//}
	//fgets(ret, count+1, pf);
	//printf("%s", ret);


	fclose(pf);
	pf = NULL;
	/*free(ret);
	ret = NULL;*/
	return 0;
}

文件中已经存入了一个字符串
用fgets将其打印
在这里插入图片描述
但是这需要提前知道文件中的字符串有多少个字符,否则只能创建一个很大的数组来存放防止其越界
那么我们可以使用fgets循环求得文件中字符的数量
并用malloc来动态创建一个刚好大小的内存来存放

#include<stdlib.h>
int main() {
	FILE* pf = fopen("myfile.txt", "r");//只读操作
	if (pf == NULL) {
		perror("fopen");
		return;
	}
	

	//输出字符串
	/*char c[25];
	fgets(c, 25, pf);
	printf("%s", c);*/
	//fgets函数的第二个参数必须要知道需要读取多少个字符,不方便
	//使用fgets循环求得文件中字符的数量
	char num[100];
	int count = 0;

	while (fgets(num, sizeof(num), pf )) {
		count += strlen(num);
	}
	rewind(pf);//重置文件指针到开头
	//printf("%d", count);
	char* ret = (char*)malloc(count+1);//留一个位置fang\0
	if (ret == NULL) {
		perror("malloc");
		fclose(pf);
		return;
	}
	fgets(ret, count+1, pf);
	printf("%s", ret);


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

在这里插入图片描述

5.3 fputs

int fputs ( const char * str, FILE * stream );

fputs 是一个在 C 语言中用于向文件写入字符串的函数。它属于标准 I/O 库的一部分,并定义在 <stdio.h> 头文件中。fputs 函数用于将一个字符串写入到一个文件中。
参数说明:

  • str:指向要写入文件的字符串的指针。
  • stream:目标文件的 FILE 指针。

返回值:

  • 如果成功,fputs 返回非负值。
  • 如果发生错误,返回 EOF(通常定义为 -1),并设置全局错误指示器。
int main() {
	FILE* pf = fopen("myfile.txt", "w");//使用w来写入数据会将以前的数据给覆盖掉
	
	if (pf == NULL) {//检查pf是否为空
		perror("fopen");
		return;
	}

	fputs("I am a handsome boy", pf);

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

在这里插入图片描述

5.4 scanf和fscanf,printf和fprintf

scanf和printf都是标准输入输出流的函数,可以从键盘上读写数据,
而fscanf何fprintf函数都是所有输入输出流的函数,可以从任意流上读写数据

6.文件读取结束的判定

6.1 feof 和 ferror

feof函数用于判断在文件读取结束后,读取结束的原因是不是遇到文件结尾而结束
ferror函数用于判断在文件读取结束后,读取结束的原因是不是遇到文件错误而结束

文本文件是否读取结束,判断返回值是否为EOF,或者NULL

  • fgetc判断是否为EOF
  • fgets判断是否为NULL

二进制文件的读取结束,判断返回值是否小于实际要读取的个数

  • fread判断返回值是否小于实际要读取的个数
/考研势在必行/
  • 24
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值