文件的操作

在这里插入图片描述

种一棵树最好的时候,一个是十年前,一个时现在

1.为什么使用文件

我们在vs里面运行一个程序时,输入的数据是存放在内存中的。当我们下次运行程序时,之前录入的数据自然就不存在了。比如说我们写了一个通讯录的程序,我们第一次运行时在里面存入了一部分人的信息,下次运行时那些数据便会消失。使用这样的通讯录是非常不合理且难受的。
这时我们就有一个需求,希望上次录入的数据能够保存下来。而这个能够帮助我们的东西就是文件。文件的数据是储存在硬盘上的,不会随着程序的运行结束而消失。

2. 什么是文件

磁盘上的文件是文件。
但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)。

程序文件

包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe。
储存我们写的代码的文件。

数据文件

文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。
我们之前在vs上的输入scanf,输出printf都是以终端为对象。即从终端的键盘输入数据,运行结果显示到显示器上。但有的时候需要我们把数据储存在磁盘上,或者有时我们要把文件的内容读取到内存中来使用。这个文件就是数据文件。
我们接下来主要介绍数据文件。

文件名

一个文件要有一个唯一的文件标识,以便用户识别和引用。
文件名包含三部分:文件路径,文件名主干,文件后缀
例:
在这里插入图片描述
为了方便起见,文件标识常被称为文件名。

3.文件的打开和关闭

文件指针

在打开一个文件的过程中在内存中编译器会自动给出一块空间来储存文件的基本信息,这些信息储存在一个结构体变量中。
该结构体类型是由系统声明的,取名为FILE

struct _iobuf {
		char *_ptr;
		int _cnt;
		char *_base;
		int _flag;
		int _file;
		int _charbuf;
		int _bufsiz;
		char *_tmpfname;
};
typedef struct _iobuf FILE;
FILE* pf;//文件指针变量

打开的过程图解:
在这里插入图片描述

文件的打开和关闭

文件的打开
ANSIC 规定使用fopen函数来打开文件,fclose来关闭文件。

//打开文件
FILE * fopen ( const char * filename, const char * mode );
                  "文件名"                "文件的使用方式"
//关闭文件
int fclose ( FILE * stream );
              指向文件的指针

例:

int main()
{
	FILE* pf = fopen("test.exe", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fclose(pf);
	pf == NULL;
	return 0;
}

注意点:
1.fopen和fclose必须同时出现。
2.由于存在文件无法打开的情况,所以要检验。(这里我们要了解fopen函数,它在打开失败时会返回NULL指针)。
3.fclose后文件指针会变成野指针,所以我们要将他赋为空指针。

文件的使用方式

在这里插入图片描述
解释一下文件不存在情况中的建立一个新文件
例1:没有文件路径时
在这里插入图片描述
例2:有文件路径时
在这里插入图片描述

4.文件的顺序读写

用于文件读写的几个函数
在这里插入图片描述
在这里插入图片描述

fputc函数

函数的原型
int fputc ( int character, FILE * stream );
             字符               文件指针
函数的应用
	int main()
{
	FILE* pf = fopen("test.txt", "w");
	'w'书写文件
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 26; i++)
	{
		fputc('a' + i, pf);
	}
	fputc('\n', pf);
	for (i = 0; i < 26; i++)
	{
		fputc('a' + i, pf);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}
	

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

fgetc函数

函数的原型
int fgetc ( FILE * stream );
             指针文件
函数的应用
int main()
{
	FILE* pf = fopen("test.txt", "r");
	'r'读取文件
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	int i = 0;
	//fputc('a', pf);
	char ch = fgetc(pf);
	printf("%c", ch);
	return 0;
}

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

fgets函数

函数原型
char * fgets ( char * str, int num, FILE * stream );
                 字符串的首地址   最多读取几个字符    文件指针
      最多读取n-1个,后面补\0 ,且读到\0会停止。其他所有字符都会读取
函数的应用
int main()
{
	FILE* pf = fopen("test.txt", "r");
	char arr[] = { "#########" };
	fgets(arr, 5, pf);
	printf("%s", arr);
	fclose(pf);
	pf = NULL;
	return 0;
}                           

文件里面的数据:
在这里插入图片描述
监视结果:
在这里插入图片描述

fputs函数

函数原型
int fputs ( const char * str, FILE * stream );
             字符串首地址          文件指针
函数的应用
int main()
{
	FILE* pf = fopen("test.txt", "w");
	char arr[] = { "abcdefghi" };
	fputs(arr, pf);
	fputs("\n", pf);
    fputs("abcdef,pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

运行结果
在这里插入图片描述

fprintf函数

函数原型
int fprintf ( FILE * stream, const char * format, ... );
我们对比一下它与scanf的区别
                int printf ( const char * format, ... );
函数的应用
int main()
{
	FILE* pf = fopen("test.txt", "w");
	char arr[20] = { "#########" };
	fprintf(pf, "%s\n %d\n %c\n", arr, 5, 'c');
	pf = NULL;
	return 0;
}

运行结果
在这里插入图片描述

fscanf函数

函数原型
int fscanf ( FILE * stream, const char * format, ... );
对比一下scanf函数
                int scanf ( const char * format, ... );
函数的应用
int main()
{
	FILE* pf = fopen("test.txt", "r");
	char arr1[10] = { 0 };
	int c = 0;
	char b = 0;
	fscanf(pf,"%s %d %c",arr1,&c,&b);
	printf("%s\n%d\n%c\n", arr1, c, b);
	pf = NULL;
	return 0;
}

这里我们用的是上面fpintf应用时存放的数据
在这里插入图片描述

fwrite函数

函数原型
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
  一片连续空间的指针  单个要读取的元素的字节数   要读取的元素个数  文件指针
  
函数的应用
int main()
{
	FILE* pf = fopen("test.txt", "w");
	int arr1[] = { 0,1,2,3,4,5,6,7 };
	fwrite(arr1, sizeof(int), 8, pf);
	pf = NULL;
	return 0;
}

运行结果
在这里插入图片描述

fread函数

函数原型
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
     一片连续空间的指针  单个要读取的元素的字节数   要读取的元素个数  文件指针
     
函数的应用
int main()
{
	FILE* pf = fopen("test.txt", "r");
	int arr1[10] = { 0 };
	fread(arr1, sizeof(int), 8, pf);
	int i = 0;
	for (i = 0; i < 8; i++)
	{
		printf("%d ", arr1[i]);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

建立在上面fwrite上的运行结果
在这里插入图片描述

补充

前面我们注意到下面这些函数适合所有输入输出流
在这里插入图片描述
那么他们怎么作用于标准输入输出流呢?
在这里插入图片描述

接下来我们尝试用fscanf来实现标准输入流,其他适用所有流的函数都类似。

int main()
{
	int a = 0;
	char b = 0;
	char arr[10] = { 0 };
	fscanf(stdin, "%d %s %c", &a, arr, &b);
	printf("%d\n%s\n%c", a, arr, b);
	return 0;
}

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

5.文件的随机读写

fseek函数

这个函数可以根据文件指针的位置和偏移量来定位文件指针

函数原型
int fseek ( FILE * stream, long int offset, int origin );
             文件指针           偏移量           文件起始位置

在这里插入图片描述

函数的应用
int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputs("abcdefgh", pf);
	fseek(pf, 4, SEEK_SET);
	fputs("hh", pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

运行结果
在这里插入图片描述

ftell函数

返回文件指针相对于起始位置的偏移量

函数原型
long int ftell ( FILE * stream );

函数的应用

int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fputs("abcdefgh", pf);
	long a = ftell(pf);
	printf("%ld\n", a);
	fseek(pf, 4, SEEK_SET);
	long b = ftell(pf);
	printf("%ld", b);
	fputs("hh", pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

运行结果
在这里插入图片描述

rewind函数

文件指针返回文件的起始位置
这个函数太简单,就不详细介绍了

void rewind ( FILE * stream );

谢谢大家的阅读!

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值