Bootstrap

测试必备技能之C语言文件函数(超级全能篇)——FILE函数

之前出过的文件FILE函数的小白篇,现在出一个全面一些的
在这里插入图片描述

以下讲解直接分为函数原型+函数作用+测试用例
让大家真真正正的理解和感受这几个FILE函数的作用

二话不说,开冲!

额…先来个小表格:

在这里插入图片描述

在这里再重复一下上一篇讲述过的几个基本的FILE函数,由于这几个函数在上一个博客都有讲过,而且比较基础简单在这里就没有测试用例啦,直接简单看函数原型和作用☺☺☺
★fopen()函数

✿、函数原型:FILEfopen(charfilename,char*type);
✿、函数作用:
打开一个“流“

★fclose()函数

✿、函数原型:
int fclose(char*filename);
✿、函数作用:
关闭一个“流“

★fprintf()函数

✿、函数原型:
int fprintf(charfilename,charformat[,argument,…])(format就是要写入的参数)
✿、函数作用:
传送格式化文本形式输出到一个流中

好了,结束了上面几个在小白篇出现的三个常用FILE函数,让我们进入正题:

首先,在这里回答一个问题:

在开始接触FILE函数这一个模块的时候,先了解一下文件的类型,常见的有二进制类的,还有文本形式类的,怎么区分呢?

简记:一个是看不懂的文字,而一个是你看得懂的在这里插入图片描述
个人认为,言简意赅,十分易记

演示一波

二进制文件:
在这里插入图片描述
文本文件:
在这里插入图片描述
简单理解了之后,细细想想这两个到底有什么区别和差异,在这里我不多加赘述,这一篇是讲述FILE函数的,所以以下内容主要对我怎么写二进制文件、怎么写文本文件等等一系列操作进行函数剖析和演示,具体这两个形式有什么具体区别,我会在下一篇出♥♥♥♥♥


feof()函数
✿、函数原型:
int feof(FILE*stream);额…和前面区别一下嘛在这里插入图片描述
✿、功能:
检测流上的文件结束符
没有什么特别意思,就是检测到你的文件到末尾了,后面没有东西了♞
✿、程序用例:

#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int main() {
	FILE* fp;
	fp = fopen("test.txt","r");
	char c = '0';//初始化中间变量
	if (fp == NULL)
	{
		printf("打开文件失败!\n");
		exit(0);
	}
	while (!feof(fp))//feof(fp)==NULL,代表已经结束,这句话非常常用
	{
		c=fgetc(fp);
		printf("%c\n",c);
	}

	if (feof(fp))
	{
		printf("We have reached the end!\n");
	}
	fclose(fp);
	return 0;
}

test.txt文件内容:
在这里插入图片描述
结果:
在这里插入图片描述
之前有些人有问到关于”空格“的问题,在这里大家可以放心,feof()函数它就是可以检测到这个文件到底有没有结束,就像这里我空了几个空格,它也会算进去的,不得不说,酷在这里插入图片描述


fgetc()函数
在上面的代码中,相信眼尖的小伙伴看到了这一句:
c=fgetc();
✿、函数原型:
int fgetc(FILE*stream);
✿、作用:
从流中读取字符(就是一个一个去读,及其好用)
✿、程序用例:
额…我写到这里我发现,咦?上面那个程序测试用例好像已经说明了这个函数的意思了
在这里插入图片描述
咳咳,那好吧,就再来其他的组合好了在这里插入图片描述


fgetchar ()、fputchar()、freopen()函数登场
✿、函数原型
int fgetchar(void);
int fputchar(char ch);
FILE *freopen(char *filename, char *type, FILE *stream);

✿、函数功能:
**fgetchar:从流中读取字符,fgetchar()其实它等价于fgetc(stdin),而且使用VS的朋友,怎么说呢,我记得好像在V C++2005年开始,fgetchar()这个函数已经被废弃了,要使用_fgetchar()代替使用,包括下面的fputchar也是前面要修改,具体看下案例代码
**fputchar:送一个字符到标准输出流(stdout)中
**freopen:将一个新的名为filename与给定的打开流stream关联,同时关闭流中的旧文件,在函数定义时的stream–它指的就是指向FILE对象的指针,该指针对象标识了要被重新打开的流

★stream常用三个值:
stdout(Standardoutput)标准输出
stdin(Standardinput)标准输入
stderr(Standarderror)标准错误

根据官网的解释就是:只是方便操作输出,比如传给一个函数等等。这时函数的输出就不是输出到文件,而是传进来的stdout文件指针,即标准输出。(stdout为例)

具体的用法如下:
✿、程序案例:

#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>

int main(void)
{
	int c;
	FILE* fp;
	fp = freopen("test.txt","r",stdin);
	if (fp != NULL)
	{
		while ((c = _fgetchar()) != EOF)//输入功能
		{
			_fputchar(c);//输出功能
		}
	}
	fclose(fp);
	return 0;
}

test文件:
在这里插入图片描述
结果:
在这里插入图片描述


现在不改变test文本内容,让我们看一看freopen()函数的“关联”特性,我们执行以下代码:

#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>

int main(void)
{
	FILE* fp;
	printf("----让文本重定向到 stdout测试---\n");
	fp = freopen("test.txt", "a+", stdout);
	printf("该文本重新定位到到 test.txt\n");
	printf("测试结束啦啦啦!");//输出变成到文件输出去了,控制台没有这一句输出了
	fclose(fp);
	return 0;
}


结果:
test.txt文件变成:
在这里插入图片描述
会发现只要使用了这个函数,它的意思就是你将你的输出就比如printf,大家都知道这个是直接输出到控制台的,可是会发现它在你的文件中输出了,有种重新指定的意味,它关联了你所指定的文件,这也是这个函数最重要的功能之一


fscanf()函数

✿、函数原型
int fscanf(FILE *stream, char *format[,argument…]);
✿、功能
从一个流中执行格式化输入
✿、程序案例:
额…先重现让test.txt文件恢复原样:
在这里插入图片描述
ok,继续

#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>

int main(void)
{
	FILE* fp;
	char c = '0';
	fp = fopen("test.txt", "r");
	while (!feof(fp))
	{
		fscanf_s(fp,"%c",&c,1);//1为缓冲区大小,就跟你用scanf_()一样
		printf("%c",c);
	}
	fclose(fp);
	return 0;
}

这个函数的作用就是跟scanf非常的像,就是简单的一个赋值的操作,也非常的常用
结果:
在这里插入图片描述
将文件中的东西通过赋值给c输出,这个函数较为简单,过过过


fwrite()函数和fread()函数姐妹花组合
前面讲的大部分用于文本文件,就比如fprintf()就是以格式化的数据写进去,fscanf_()也是一般用于文本的读取,那么对于二进制文件我们应该怎么处理呢?这两个函数便是主要用于处理二进制读写的函数

除此之外呢,这两个函数主要是读取“数据块”,看它的函数原型在这里插入图片描述

✿、函数原型
int fread(void *ptr, int size, int nitems, FILE *stream);
int fwrite(void *ptr, int size, int nitems, FILE *stream);
解释一下:
ptr指的就是表示存放输入数据的首地址(一般会用数组)
size是指数据块的字节数,nitems是指读取的数据块的个数
比如说:fread(arr,4,5,fp)意义就是从fp所指的文件中,每次读入4个字节送入到arr数组中,连续读五次
✿、功能
这两个函数相信大家字面意思也能懂了,就是一个读、一个写,就是这么狠在这里插入图片描述
具体看下在这里插入图片描述

而且而且大家一定要注意的是:在读写二进制文件时候,必须确保文件的打开形式是以二进制读写的形式打开的,即类似“rb”,"wb"等在这里插入图片描述

✿、程序案例:
举一个非常简单的例子
fwrite():

#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>


int main()
{
	FILE* fp;
	fp = fopen("test_1.data","rb+");
	int buf[40];
	char arr[40] = "\0";
	char c = '\0';
	int i = 0;
	if (fp == NULL)
	{
		printf("faile open the file\n");
		exit(0);
	}
	
	for (int i = 0; i < 5; i++)
	{
		scanf_s("%d",&buf[i]);
	}
	fwrite(buf,sizeof(int),5,fp);
	fclose(fp);
	return 0;
}

测试输入:10100
结果:在这里插入图片描述

乱码(字节大小:20(int是4,5个4=20))
在这里插入图片描述
就着上面已经有的这个二进制文件,我们用fread()函数去解读它:

#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>


int main()
{
	FILE* fp;
	fp = fopen("test_1.data","rb+");
	int buf[40];
	int arr[40];
	char c = '\0';
	int i = 0;

	fseek(fp,SEEK_SET,0);//从文本开头开始读取
	fread(arr,20,1,fp);

	for (int i = 0; i < 5; i++)
	{
		printf("%d",arr[i]);
	}

	fclose(fp);
	return 0;
}

结果:在这里插入图片描述
不得不说,强大在这里插入图片描述


fseek()函数
这个函数比较简单理解,就是规定文件指针位置,比如你不想每次都从文件首部开始,想从一个特定的位置开始,那么这个函数就是起到这样一个作用的
✿、函数原型
int fseek(FILE *stream, long offset, int fromwhere);
✿、功能
重新定义流上的文件指针
offset:相对于fromwhere的偏移,以字节为单位
fromwhere:偏移的位置
一般指定为下列三个常量之一:
SEEK_SET 文件的开头
SEEK_CUR 文件指针的当前位置
SEEK_END 文件的末尾

✿、程序案例
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>


int main()
{
	FILE* fp;
	fp = fopen("test.txt","r");
	char c = '0';
	if (fp == NULL)
	{
		printf("fail open the file!\n");
		exit(0);
	}
	printf("现在从距离起点4个字节位置开始读取:\n");
	fseek(fp,4,SEEK_SET);
	while (!feof(fp))
	{
		fscanf_s(fp,"%c",&c,1);
		printf("%c",c);
	}
	fclose(fp);
	return 0;
}

结果:
在这里插入图片描述
基于这个函数比较简单,大家可以自己去玩一玩,在这里不赘述更多的测试用例了在这里插入图片描述


ftell()函数

✿、函数原型:
long ftell(FILE *stream);
✿、功能:
返回当前文件的指针(额…就是文件字节数啦)
✿、程序测试用例:

#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>


int main()
{
	FILE* stream;
	stream = fopen("test.txt", "w+");
	fprintf(stream, "This is a test");
	printf("The file pointer is at byte % ld\n", ftell(stream)); 
	fclose(stream);

	return 0;
}

结果:
在这里插入图片描述
在这里插入图片描述


fgets()函数
前面讲了fgetc()函数,现在来一个它的兄弟在这里插入图片描述
✿、函数原型:

char *fgets(char *string, int n, FILE *stream);
✿、功能
从流中读取字符串
✿、程序案例:

#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>


int main()
{
	FILE* stream;
	char string[] = "I am X BIG MONSTER";
	char msg[20];
	stream = fopen("test.txt", "w");
	fwrite(string, strlen(string), 1, stream);
	fseek(stream, 0, SEEK_SET);
	fgets(msg, strlen(string) + 1, stream);
	fclose(stream);


	return 0;
}

结果:
在这里插入图片描述

总结

还是那句话,自己多动手,就会发现奥妙之处在这里插入图片描述
可能不够完善,我会努力更哒在这里插入图片描述

;