文件操作知识点

一.文件有不同的类型,分为两种文件:

程序文件(包括源文件.c,目标文件.obj,可执行文件.exe,这些文件的内容是程序代码)
数据文件(文件内容不一定是程序,而是程序运行时读写的数据,比如成绩数据,交易数据)

二.何为文件?

文件是程序设计中一个重要的概念,何为文件? 文件一般指的是存储在外部介质上数据的集合.也就是说,一批数据以文件的形式存放在外部的磁盘介质上,如果我们想要找存放的数据的时候,必须先按文件名找到文件,再从文件里面读取数据.当然外部介质中也必须建立一个文件,我们才能向他输出数据

需要注意的是操作系统把各种设备都统一作为文件来处理,从操作系统的角度看,每一个与主机联系的输入输出设备都是文件,比如,终端输入键盘是输入文件,显示屏和打印机就是输出文件.

我们在这里讨论的是对数据文件的操作

三.文件名

一个文件要有唯一的文件标识,便于用户识别,文件标识分为三部分 :文件路径,文件名主干,文件后缀

在这里插入图片描述

文件后缀,不一定就是文件的打开方式,他只是系统默认这个方式打开,其实我们用其他方式也可以打开只是打开之后,可能不是我们所要的东西.

文件标识就常被称为文件名

在这里我们需要了解的是,我们上面这个路径是一个绝对路径,何为绝对路径?

路径标识了唯一的文件,(以盘符C: D: E: 开头 或根目录开头linux 中以 / 开头)

有了绝对路径那么就有相对路径:相对路径(以 " . “, 或者”. ."开头的) " ." 表示当前目录 ". . "表示当前目录的上一层,相对路径必须有一个"当前目录"必须指定当前目录 比如

在这里插入图片描述

在写工程中我们相对路径用的多,因为我们是要发布给用户的,所以我们在我们的电脑下用一个绝对路径,这在我们的电脑上是唯一且存在的,那么不一定在用户的电脑上是存在的!

四.数据文件的分类

根据数据的组织形式,数据文件可分为ASCII文件和二进制文件
一个数据怎么在介质中存储?

字符一律以ASCII形式存储,数值型文件既可以用ASCII形式,也可以用二进制存储

在这里插入图片描述

六.文件缓冲区概念

ANSI C 采用 缓冲文件系统 处理数据文件,系统自动的在内存区为程序中每一个正在使用的文件开辟一个文件缓冲区,从内存向磁盘输出数据必须先送到内存中的缓冲区,装满缓冲区后才一起从到磁盘,如图,装在数据也是一样,先从磁盘取数据到缓冲区,再到层序数据区操作数据,再输出

在这里插入图片描述

缓存和缓存区的区别详解

七.文件类型指针

在文件缓冲系统中,关键的概念是"文件类型指针",简称 “文件指针”,每个被使用的文件在内存中开辟一个信息区,用来存放文件的有关信息(比如文件的名字,状态,当前位置),这些信息保存在一个结构体变量里面,这个结构体变量是由系统声明的,在stdio.h有文件中包含

struct _iobuf {
        char *_ptr;
        int   _cnt;
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname;
        };
typedef struct _iobuf FILE;

这个声明是VS2010中的声明,在不同的编译系统中可能声明不一样,里面包含的就是文件的各种信息,我们不用深究.

FILE f1;  

我们定义了一个结构体变量f1 ,用它来存放一个文件的有关信息,这些信息是在打开文件时由系统根据文件的情况自动放入的,我们不必过问.

我们一般不会对FILE类型变量命名,也就是不通过变量的名字来用这个变量,而是设置一个文件指针变量来用

FILE *fp;

定义一个变量用来指向文件的信息区(他就是一个结构体变量),而我们通过文件信息区中的信息就能够访问这个文件,也就是说我们通过这个指针变量就可以找到与他关联的文件,这就是句柄思想,正如遥控器一样,我们不直接在电视上做操作,通过遥控器就可以来操作电视.

在这里插入图片描述

七.文件的基本操作

围绕文件有四个最基本的操作:

1.打开文件,关闭文件

文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。如过不关闭的话会如内存泄露一样造成文件泄露,在vs中默认的配置是打开512个文件,但实际我们只能打开509个,因为还有stdin,stdout,stderr
打开文件的数目是可以配置的

打开文件函数 fopen;

FILE * fopen ( const char * filename, const char * mode );
int fclose ( FILE * stream );

在定义中我们可以看出打开文件会返回一个FILE*(返回了一个文件信息区的地址) 这时候我们定义一个FILE* ,就可以对文件进行操作了

FILE* fp = fopen("../test.txt","r");
if(fp == NULL) {
	perror ("fopen");
	printf("%s\n",strerror (errno));
	return 1;
}
fclose(fp);

我们用只读的方式打开一个文件注意我创建文件的位置

在这里插入图片描述
这是我们程序的文件,也就是我们的当前目录,我们在当前目录下的上一层创建了test.txt,为什么要在上一层创建,而不再这一层创建恩呢?
当前目录的上一层
在这里插入图片描述

因为我们的程序是要发布给用户的,用的是.exe程序,所以我们不可能把源程序发布给用户,而我们的exe文件在 Debug 文件中存放,所以我们运行Debug中的exe时候,程序执行到打开文件时候,也可以使用这个路径方便一点.

如果我们打开文件失败那么有两种原因:1.文件不存在2.文件操作没有权限)
这时候我们用错误代码提示就可以查出问题所在 (异常处理机制)

文件的打开方式有很多种 如图
在这里插入图片描述

3.读文件

常用的文件操作函数

在这里插入图片描述

fread是一个函数,它从文件流中读数据,最多读取count个项,每个项size个字节,如果调用成功返回实际读取到的项个数(小于或等于count),如果不成功或读到文件末尾返回 0。

size_t fread ( void *buffer, size_t size, size_t count, FILE *stream) ;

实例:我们在txt中输入这几个字符
在这里插入图片描述

char buf[1024] =  { 0 };
size_t count = 0;
FILE* fp = fopen("../test.txt","r");
if(fp == NULL) {
		perror ("fopen");
		/*printf("%s\n",strerror (errno));*/
		return 1;
	}
count = fread(buf,1,sizeof(buf),fp);
printf("%s\ncount = %d\n",buf,count);
 

运行之后我们顺利的读到了TXT文本下的内容
在这里插入图片描述
在这里需要注意第一点 fread 是有返回值的,返回的是我们成功读到的个数,count = 12
第二点 :如何写fread 中的参数

		 void *buffer                  buf 顾名思义就是缓存的意思,存放从文件读入的数据的地址
		 size_t size,					我们一次要读写的字节数
		 size_t count				我们要读写多少个数据项
		 FILE *stream				要读写的文件流

再来举一个例子:

struct Student_type {
	char name[1024];
	int num;
	int age;
	char addr[1024];
}stdu[40];

我们定义了一个结构体数组stud,有40个数组,每一个元素来存放学生的数据,我们假设学生的数据已经录入到磁盘中,那么就可以这样写,从磁盘中读取这些数据,假设我们已经读入到FILE* fp中

for(int i = 0;i<40;i++) {
fread(&stud[i],sizeof(struct Student_type),1,fp)
}

4.写文件

文件操作都是相对应的,也就是成对出现的,由上面的图我们就可以看出来

与fread 对应的是 fwrite

fwrite() 是 C 语言标准库中的一个文件处理函数,功能是向指定的文件中写入若干数据块,如成功执行则返回实际写入的数据块数目。该函数以二进制形式对文件进行操作,不局限于文本文件。

在我们写程序时多用这两个函数读写文件,因为他们不局限文件格式

实例:我们还是以上面的程序为基准

char buf2[1024] = "hello";                    //文件缓冲区,要写/要读的东西放到内存中,最后再使用或者写到磁盘中去
FILE* fp = fopen("../test.txt","w");          //"w"打开文件的时候,会清空文件的原有内容!
if(fp == NULL) {
		perror ("fopen");
		/*printf("%s\n",strerror (errno));*/
		return 1;
	}
fwrite(buf2,1,strlen(buf2),fp);

在这里插入图片描述

这时候我们运行程序是看不出有什么效果的,因为我们写操作是在文件上完成的,注意的是"w"方式打开文件 的时候,会清空原有内容,我们要根据自己的情况来填写需要完成的操作方式!

		 void *buffer                 与上面刚好相反,把此地址开始的数据向文件输入
		 size_t size,					我们一次要读写的字节数
		 size_t count				我们要读写多少个数据项
		 FILE *stream				要写的文件流

猜你喜欢

转载自blog.csdn.net/weixin_44077227/article/details/89739319
今日推荐