文件读写介绍

文件指针

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

在这里插入图片描述

FILE* p;//文件指针

文件的打开和关闭

(1)fopen 用来打开文件,fclose用来关闭文件

//打开文件
FILE* pf = fopen(const char* filename,const char*mode);//如果返回打开失败的话会返回空指针
if(pf==NULL)//这里保证pf打开失败后操作停止
{
perror("fopen")//这是分析打开失败的原因
return 1//停止操作
}

//关闭文件
int fclose(FILE*stream);
pf=NULL;

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/b80535983d884f6d82872a61df7f68b4.png

(2)文件打开方式
在这里插入图片描述
“r”只读 如果没有相对应的文件那么就会出错
“w”只写如果没有相对应的文件那么就会创立一个新的文件,如果那个文件存在那么就会使存在的那个文件的内容全部删除,从头开始
“r”(只读)操作文件(没有先对应的文件会报错)

	FILE* pf = fopen("test.txt", "r");//如果返回打开失败的话会返回空指针
	if (pf == NULL)//这里保证pf打开失败后操作停止
	{
		perror("fopen");//这是分析打开失败的原因
			return 1;//停止操作
	}

	//关闭文件
	int fclose(FILE * stream);
	pf = NULL;
	return 0;

在这里插入图片描述
如果有文件
在这里插入图片描述
操作成功
在这里插入图片描述

理解 只读和只写
从<文件>里面拿数据到<程序> 这个过程叫读操作
从<程序>里面写数据到<文件>这个过程叫写操作
图片理解
在这里插入图片描述

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/f9e20dd0f25543deab858ed8e4b6bbee.p

文件顺序读写

(1)顺序读写函数介绍

文件流,标准输入\出流 (输出)-stdout (输入)-stdin
在这里插入图片描述

#include<stdio.h>
struct S
{
	char name[20];
	int age;
	float score;
};
int main()
{
	struct S s1 = { "李四",18,80.3 };
	FILE* pf = fopen("twt.txt", "w");//如果返回打开失败的话会返回空指针
	if (pf == NULL)//这里保证pf打开失败后操作停止
	{
		perror("fopen");//这是分析打开失败的原因
		return 1;//停止操作
	}
	//写文件-是以文本文件的形式写进去 这样才能看得懂
	fprintf(stdout, "%s %d %f", s1.name, s1.age, s1.score);//运用stdout打印在屏幕上
	//关闭文件
	int fclose(FILE * stream);
	pf = NULL;
	return 0;
}

在这里插入图片描述

(1) 那么我们就可以实现一个<写数据>然后<读数据>的操作
fputc
在这里插入图片描述
<写文件>

	FILE* pf = fopen("test.txt", "w");//如果返回打开失败的话会返回空指针
	if (pf == NULL)//这里保证pf打开失败后操作停止
	{
		perror("fopen");//这是分析打开失败的原因
			return 1;//停止操作
	}
	//写文件
   putc('a',pf);//把一个字符写到指定文件中
	//关闭文件
	int fclose(FILE * stream);
	pf = NULL;
	return 0;

在这里插入图片描述
<读文件>
在这里插入图片描述
在指定文件读,返回int(返回的是字符的ASCLL码值)
**
加粗样式
同理

	FILE* pf = fopen("test.txt", "r");//如果返回打开失败的话会返回空指针
	if (pf == NULL)//这里保证pf打开失败后操作停止
	{
		perror("fopen");//这是分析打开失败的原因
			return 1;//停止操作
	}
	//读文件
	int a=0;
   a = fgetc(pf);//把指定文件中的数据读到程序里
   printf("%c",a);
	//关闭文件
	int fclose(FILE * stream);
	pf = NULL;
	return 0;

在这里插入图片描述

(2) fputs
在这里插入图片描述
把一个字符串写到一个文件里

	FILE* pf = fopen("tat.txt", "w");//如果返回打开失败的话会返回空指针
	if (pf == NULL)//这里保证pf打开失败后操作停止
	{
		perror("fopen");//这是分析打开失败的原因
			return 1;//停止操作
	}
	//写文件
   fputs("abcdefgh",pf);//把abcdefgh这个字符串传到文件里,实际上是把字符串的首地址放到文件里
   
	//关闭文件
	int fclose(FILE * stream);
	pf = NULL;
	return 0;
	

在这里插入图片描述
fgets
在这里插入图片描述
从流(文件)里面读数据,读到的字符放在一个数组里,num是读取的个数(其中最后一个是’\0‘)这样我们就只能读(num-1)个字符

FILE* pf = fopen("test.txt", "r");//如果返回打开失败的话会返回空指针
	if (pf == NULL)//这里保证pf打开失败后操作停止
	{
		perror("fopen");//这是分析打开失败的原因
			return 1;//停止操作
	}
	//读文件
   char arr[20]={0};
   fgets(arr,10,pf);//读10-1个字符 读到arr里面 从pf FILE*指针里面读(流)
   
   
	//关闭文件
	int fclose(FILE * stream);
	pf = NULL;
	return 0;

在这里插入图片描述
fgets读取出错时或者读到文件末尾时会返回NULL(空指针)
如果想要让fgets读取文件的所有元素

FILE* pf = fopen("test.txt", "r");//如果返回打开失败的话会返回空指针
	if (pf == NULL)//这里保证pf打开失败后操作停止
	{
		perror("fopen");//这是分析打开失败的原因
			return 1;//停止操作
	}
	//读文件
   char arr[20]={0};
   
   while(fgets(arr,10,pf))//读10-1个字符 读到arr里面 从pf FILE*指针里面读(流)
   {
   printf("%s",arr);
   }
   
	//关闭文件
	int fclose(FILE * stream);
	pf = NULL;
	return 0;

fgets会拆成多次打印直到出错或遇到文件末尾
在这里插入图片描述

(3)fprintf(各式化的输出函数)
在这里插入图片描述
这与printf的函数就差了个文件指针

	struct s s1 = { "李四",18,80.3 };
	FILE* pf = fopen("twt.txt", "w");//如果返回打开失败的话会返回空指针
	if (pf == NULL)//这里保证pf打开失败后操作停止
	{
		perror("fopen");//这是分析打开失败的原因
		return 1;//停止操作
	}
	//写文件-是以文本文件的形式写进去 这样才能看得懂
	fprintf(pf, "%s %d %f", s1.name, s1.age, s1.score);
	//关闭文件
	int fclose(FILE * stream);
	pf = NULL;
	return 0;

在这里插入图片描述
fscanf(格式化的输出函数)格式化就可以打印浮点型数字等等
在这里插入图片描述
多了个FILE* 文件指针

struct B
{
char name[20];
int gae;
float score;
};
int main()
{
struct B b={0};
//想从文件twt.txt中读取数据放在结构体B中
FILE* f=fopen("twt.txt","r");
if(f==NULL)
{
perror("fopen");
return 1;
}
//读文件
fscanf(f,"%s %d %f",b.name,&(b.age),&(b.score))//这里的name已经是地址了所以不用&
printf("%s %d %f",b.name,b.age,b.score);
//关闭文件
fclose(f);
f=NULL;

在这里插入图片描述
(4)函数对比
在这里插入图片描述

printf-把数据以格式化的形式打印在标准输出流上
fprintf-把数据以格式化的形式打印在指定的输入流上

sprintf 把格式化的数据打印到字符数组里
在这里插入图片描述
在这里插入图片描述
对比一下 sprintf的功能是以格式化的数据转换成字符串
printf的功能是把格式化数据打印到标准流里

操作

struct S
{
char name[20];
int age;
float score;
};
int main()
{
char arr[200]={0};
struct S s={"张三",20,65.5};
sprintf(arr,"%s %d %f",s.name,s.age,s.score);//把格式化的数据以字符的方式打印到字符数组里
printf("%s\n",arr);
return 0;
}

在这里插入图片描述

scnaf -从标准输入流上读取格式化的数据(标准输入流就是以键盘输入到程序中)
fscanf - 从指定输出入流上读取格式化的数据
sscanf - 在字符串中读取格式化数据

在这里插入图片描述
在这里插入图片描述
对比scanf与sscanf就是多了一个字符数组

struct S 
{
char name[20];
int age;
float score;
};
int main()
{
	char arr[200] = { 0 };
	struct S s = { "张三",20,65.5 };
	sprintf(arr, "%s %d %f", s.name, s.age, s.score);//把格式化的数据以字符的方式打印到字符数组里
	struct S s1 = { 0 };
	sscanf(arr, "%s %d %f", s1.name, &(s1.age), &(s1.score));//从字符串读取数据
	printf("%s %d %f",s1.name,&s1.age&,s1.score);
	printf("%s\n", arr);

	return 0;

在这里插入图片描述
(5)fwrite与fread
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
ptr是个数组地址,把ptr的数据以二进制形式写到文件中
size是数组的类型
count是指要写几个数据到文件中
FILE*stream是文件地址

#include<stdio.h>
int main()
{
	//打开文件
	FILE* pf = fopen("test.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//写数据
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	fwrite(arr, sizeof(arr), 5, pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

在这里插入图片描述
fread
在这里插入图片描述

在这里插入图片描述
与fwrite对比参数一样
从pf文件中读count个数据打印到数组ptr里

#include<stdio.h>
int main()
{
	//打开文件
	FILE* pf = fopen("test.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	int arr[10] = { 0 };
	//写数据
	fread(arr, sizeof(arr), 5, pf);
	int i = 0;
	for (i = 0;i < 5;i++)
	{
		printf("%d ", arr[i]);
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

在这里插入图片描述

fread返回值size_t返回1为真返回0为假

#include<stdio.h>
int main()
{
	//打开文件
	FILE* pf = fopen("taat.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读数据
	int arr1[5] = { 0 };
	int i = 0;
	while (fread(&arr1[i], sizeof(int), 1, pf))
	{
		printf("%d ", arr1[i]);
	}
		

	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

在这里插入图片描述

文件的随机读取

1:fseek
在这里插入图片描述
在这里插入图片描述
而起始位置有三种选择
在这里插入图片描述
(1):SEEK_SET 文件起始位置
(2):SEEK_CUR文件的当前位置
(3):SEEK_END文件末尾

#include<stdio.h>
int main()
{
	//打开文件
	FILE* p = fopen("tbt.txt", "w");
	if (p == NULL)
	{
		perror("fopen");
		return 1;
	}
	//写文件
	fputs("abcdefg",p);
	//关闭文件
	fclose(p);
	p = NULL;
	FILE* pf = fopen("tbt.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读文件
	int a = fgetc(pf);
	printf("%c\n", a);
	fseek(pf, 4,SEEK_CUR);//改变光标指向的值
	a = fgetc(pf);//在让a等于getc(pf)
	printf("%c", a);//以字符类型打印a
	//关闭文件
    fclose(pf);
	pf = NULL;
	     return 0;
}

在这里插入图片描述
当第一次以fgetc来取字符是,光标位于第一位
而经过fseek的操控后光标偏移到指定地点

ftell
返回文件指针相对于起始位置的偏移量
在这里插入图片描述

#include<stdio.h>
int main()
{
//打开文件
	FILE* pf = fopen("tgt.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//写文件
	fputs("abcdefgh", pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	//打开文件
	FILE* p = fopen("tgt.txt", "r");
	if (p == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读文件
	int ch = 0;
	ch = fgetc(p);
	fseek(p, 0, SEEK_END);
	printf("%d", ftell(p));
	//关闭文件
	fclose(p);
	p = NULL;
	return 0;
}

在这里插入图片描述
rewind
在这里插入图片描述
测试一下

#include<stdio.h>
int main()
{
	FILE* pf = fopen("tgt.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputs("abcdefgh", pf);
	fclose(pf);
	pf = NULL;
	FILE* p = fopen("tgt.txt", "r");
	if (p == NULL)
	{
		perror("fopen");
		return 1;
	}
	int ch = 0;
	ch = fgetc(p);
	printf("%c\n", ch);
	fseek(p, 0, SEEK_END);
	rewind(p);
	ch = getc(p);
	printf("%c", ch);
	fclose(p);
	p = NULL;
	return 0;
}

在这里插入图片描述

文件读取结束的判定

feof
在这里插入图片描述
在这里插入图片描述
fgetc-如果读取正常返回的是字符的ASCLL码值
-如果读取的过程中遇到文件末尾,或发生错误,就返回EOF
fgets 如果读取正常,返回的是存储读取到的字符串的字符数组的地址
如果读取过程中遇到文件末尾或发生错误,返回NULL
在这里插入图片描述

feof 功能 :来检测文件末尾是否被标记,如果被标记了就返回一个大于0的值,没有被设置的话就返回一个0.

ferror
在这里插入图片描述
ferror去检测错误标记被设置了,那么就会返回非0值否则就返回0;

#include<stdio.h>

int main()
{
	FILE* p = fopen("test.txt", "r");
	if (p == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读文件
	int ch = 0;
	while ((ch = fgetc(p)) != EOF)//当ch等于EOF时就跳出while
	{
		printf("%c", ch);
	}
	//采用feof来判断
	if (feof(p))
	{
		printf("遇到文件末尾,读取正常结束");
	}
	else if (ferror(p))//
	{
		perror("fgetc");//打印出错误原因
	}


	return 0;

}

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值