【文件指针+文件顺序读写操作函数】
创始人
2024-05-13 00:51:33
0

1.文件的打开和关闭

  • 1.1 什么是文件指针

2.文件操作函数

  • 2.1 fgetc函数和fputc函数
  • 2.2 fgets函数和fputs函数
  • 2.3 fscanf函数和fprintf函数
  • 2.4 fwrite函数和fread函数

1.文件的打开和关闭

1.1 什么是文件指针?

每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名
字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统
声明的,取名FILE.

假如:我们要操作一个文件,名为text.txt ,首先要打开文件,打开文件的同时,操作系统会自动为该文件创建一个文件信息区,专门用来记录该文件的信息。

在这里插入图片描述
文件信息区的每一个信息与text.txt的信息是一一对应的。而该文件信息区名为struct _iobuf,又被重命名为 FILE 。

所以FILE其实就是文件信息区。

每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,使用者不必关心细节。

一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。

下面我们可以创建一个FILE*的指针变量:

FILE* pf; 文件指针变量

通过该文件指针变量,我们就可以读写文件中的信息。

文件在读写之前,需要打开文件

//打开文件
FILE * fopen ( const char * filename, const char * mode );

读写文件完成后,需要关闭文件:

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

文件的打开方式如下:

在这里插入图片描述
举个例子:

#include 
int main ()
{//打开文件
FILE* pFile = fopen ("text.txt","w");//文件操作if (pFile!=NULL)
{fputs ("fopen",pFile);//关闭文件fclose (pFile);
}return 0;
}

该段代码的意思是:打开一个文件叫text.txt,以写的形式打开。意味着向文件中写入信息。具体是怎么写的,下面会讲到。
写完信息后关闭文件,fclose(pFile),pFile就是一个文件指针。

文件指针就是用来操作文件的,假如我们需要对文件进行写入的操作,就使用文件指针打开该文件并定义"写"的操作。

2.文件操作函数

在这里插入图片描述

2.1 fgetc函数和fputc函数

fgetc函数和fputc函数是针对字符的输入输出的。

int fgetc(FILE* stream);
//从流中读取字符,返回读到的ascii码值

流是什么呢?可以把流理解成水流,水流到尽头,就是一个蓄水池。一个蓄水池就相当于一个存储大量文件的区域。文件也类似,从流中(文件信息区)中读取文件,fgetc返回读到的ascii码值。

int fputc(int character, FILE* stream);
//把字符character 写入流中

fputc是将一个字符写入文件中。一次写入一个字符,返回成功写入的字符的个数。

举个例子:

int main()
{FILE* pf =fopen("text.txt", "w");if (pf == NULL){perror("fopen");return 0;}//写入字符char ch = 0;for (ch = 'a'; ch <= 'z'; ch++){fputc(ch, pf);}fclose(pf);pf = NULL;return 0;
}

先打开text.txt文件,如果不存在该文件,则会新建一个文件("w"写入的形式会新建一个文件,但是以"r"的形式打开文件,如果文件不存在,会读取文件失败,返回NULL)

然后向文件中写入a~z个字母。

运行成功,成功写入文件:
在这里插入图片描述

写入成功,现在向文件中读取数据

int main()
{FILE* pf = fopen("text.txt", "r");if (pf == NULL){perror("fopen");return 0;}//写入字符char ch = 0;for (ch = 'a'; ch <= 'z'; ch++){int ch = fgetc(pf);printf("%c ", ch);}fclose(pf);pf = NULL;return 0;
}

读取成功,如下图:
在这里插入图片描述
总结:fgetc函数是向文件指针pf(或者其他名字,由你来定)一次读取一个字符,读取完第一个字符后,指针自动跳到下一个字符。
fputc函数是向pf指向的指针一次写入一个字符。

2.2 fgets函数和fputs函数

int fputs(const char* str, FILE* stream);
向流中写入一行数据,一次性写一行

举个例子:

int main()
{FILE* pf = fopen("text.txt", "w");if (pf == NULL){perror("fopen");return 0;}fputs("Hello World","w"); fclose(pf);pf = NULL;return 0;
}

写入成功。
在这里插入图片描述
注意:打开文件进行写入操作时,上一次写入的数据将会被清除。

接下来向从文件中读取数据:

int main()
{FILE* pf = fopen("text.txt", "r");if (pf == NULL){perror("fopen");return 0;}//读文件,一次读一行char buf[20];fgets(buf, 10, pf); // 读10个字节,相当于读9个,最后一个字节留着放\0printf("%s\n", buf);fclose(pf);pf = NULL;return 0;
}

注意:当我们读取10个字节时,实际上打印出来只打印前面9个字节的内容,还有一个字节是被用来留着放\0的。

还有一种情况,假如我们需要读取20个字节的数据,然而第一行不足20个字节,fgets读完所有的数据后,即使不够20个字节,就不会再读取了,就停止了。不会跳到第二行继续读。 更说明fges是一次只读取一行。

2.3 fscanf函数和fprintf函数

前面说过,fscanf函数和fprintf函数是格式化输入输出函数。什么是格式化函数呢?
其实格式化函数就是对于不同格式的数据都能够进行输入输出,比如:整型,浮点型,结构体类型等等,这些就是不同格式的数据。

相较于scanf和printf函数,fscanf函数和fprintf只是多了一个参数,即FILE指针所指向的文件。fscanf函数是向FILE的指针指向的文件中读取格式化的数据,fprintf函数是向FILE*的指针指向的文件中写入格式化的数据。

对比如下:

int fscanf ( FILE * stream, const char * format, ... );
int scanf ( const char * format, ... );
int fprintf ( FILE * stream, const char * format, ... );
int printf ( const char * format, ... );

举一个简单的例子:
向text.txt文件中写入结构体数据

int main()
{FILE* pf = fopen("text.txt", "w");if (pf == NULL){perror("fopen");return 0;}struct S{char name[20];int age;float score;}s = {"zhangsan",20,99.5f};fprintf(pf,"%s %d %f", s.name, s.age, s.score);fclose(pf);pf = NULL;return 0;
}

运行成功后,文件中就有了该结构体的数据。

在这里插入图片描述
对于fscanf来说亦是如此:

在这里插入图片描述
以读的方式打开该文件,对其中的数据进行读取。读取后,打印出来看即可。

s.name不用&的原因是,s.name是一个数组名,表示首元素地址,不需要&,而其他的age和score则需要&。

前面说过,这几个函数都是适用于所有输入流输出流,那么就包括了键盘(标准输入流),屏幕(标准输出流)。

int main()
{int ch = fgetc(stdin);fputc(ch, stdout);
}

此时,我们会从键盘中读取一个字符,写入到屏幕中。
在这里插入图片描述
对于其他函数也是如此。仍可以从键盘中读取数据,写入到屏幕上。

2.4 fwrite函数和fread函数

上面提到,fwrite函数和fread函数是以二进制的形式进行写入和读取的。

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

先来看看fwrite在库中的声明。
fwrite函数是向stream这个流中一次写count个大小为size的ptr指向的内容。
看不懂没关系,举个例子:

typedef struct S
{char name[20];int age;float score;
}S;int main()
{S s = { "zhangsan",20,95.5f };FILE* pf = fopen("text.txt", "wb");if (pf == NULL){perror("fopen");return 0;}fwrite(&s, sizeof(S), 1, pf);fclose(pf);pf = NULL;return 0;
}

此时我们创建了一个结构体,该结构体有三个成员,我们以二进制写入的形式打开文件进行写入,此时向pf指向的文件中写入s这块空间,一次写入1个sizeof(S)大小的内容。

运行成功后,打开text.txt文件:
在这里插入图片描述

你会发现出了拼音zhangsan,其他的都看不懂,没关系,因为这是二进制形式。
看不懂并不代表代码是错误的。

既然我们看不懂,我们就让编译器来看,下面我们以二进制读取的方式,向文件中读取数据出来。

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

既然是读取,那么就是跟写入相反而已。
从stream流指向的文件中读取ptr这块空间的内容,一次读取count个大小为size个字节的内容。

typedef struct S
{char name[20];int age;float score;
}S;int main()
{S s = { 0 };FILE* pf = fopen("text.txt", "rb");if (pf == NULL){perror("fopen");return 0;}fread(&s, sizeof(S), 1, pf);printf("%s %d %f", s.name, s.age, s.score);fclose(pf);pf = NULL;return 0;
}

此时我们向pf流指向的文件中读取s这块空间的内容,一次读取1个大小为sizeof(S)个字节的内容。读取成功后,我们就打印出来看看。
在这里插入图片描述
打印结果确实符合预期。

总结:fwrite 和fread函数是向文件中以二进制的形式写入和读取文件的。

相关内容

热门资讯

美国不提安卓系统华为,迈向自主... 华为与美国:一场关于技术、市场与政策的较量在当今这个数字化的世界里,智能手机已经成为我们生活中不可或...
安卓系统怎么打开ppt,选择文... 你有没有遇到过这种情况:手里拿着安卓手机,突然需要打开一个PPT文件,却怎么也找不到方法?别急,今天...
谷歌退回到安卓系统,探索创新未... 你知道吗?最近科技圈可是炸开了锅,谷歌竟然宣布要退回到安卓系统!这可不是一个简单的决定,背后肯定有着...
安卓系统待机耗电多少,深度解析... 你有没有发现,手机电量总是不经用?尤其是安卓系统,有时候明明没怎么用,电量就“嗖”的一下子就下去了。...
小米主题安卓原生系统,安卓原生... 亲爱的手机控们,你是否曾为手机界面单调乏味而烦恼?想要给手机换换“衣服”,让它焕然一新?那就得聊聊小...
voyov1安卓系统,探索创新... 你有没有发现,最近你的手机是不是变得越来越流畅了?没错,我要说的就是那个让手机焕发青春的Vivo V...
电脑刷安卓tv系统,轻松打造智... 你有没有想过,家里的安卓电视突然变得卡顿,反应迟钝,是不是时候给它来个“大保健”了?没错,今天就要来...
安卓系统即将要收费,未来手机应... 你知道吗?最近有个大消息在科技圈里炸开了锅,那就是安卓系统可能要开始收费了!这可不是开玩笑的,这可是...
雷凌车载安卓系统,智能出行新体... 你有没有发现,现在的汽车越来越智能了?这不,我最近就体验了一把雷凌车载安卓系统的魅力。它就像一个聪明...
怎样拍照好看安卓系统,轻松拍出... 拍照好看,安卓系统也能轻松搞定!在这个看脸的时代,拍照已经成为每个人生活中不可或缺的一部分。无论是记...
安卓车机系统音频,安卓车机系统... 你有没有发现,现在越来越多的汽车都开始搭载智能车机系统了?这不,咱们就来聊聊安卓车机系统在音频方面的...
老苹果手机安卓系统,兼容与创新... 你手里那台老苹果手机,是不是已经陪你走过了不少风风雨雨?现在,它竟然还能装上安卓系统?这可不是天方夜...
安卓系统7.dns,优化网络连... 你有没有发现,你的安卓手机最近是不是有点儿“慢吞吞”的?别急,别急,让我来给你揭秘这可能与你的安卓系...
安卓手机系统怎么加速,安卓手机... 你有没有发现,你的安卓手机最近变得有点“慢吞吞”的?别急,别急,今天就来给你支几招,让你的安卓手机瞬...
小米note安卓7系统,探索性... 你有没有发现,手机更新换代的速度简直就像坐上了火箭呢?这不,小米Note这款手机,自从升级到了安卓7...
安卓和鸿蒙系统游戏,两大系统游... 你有没有发现,最近手机游戏界可是热闹非凡呢!安卓和鸿蒙系统两大巨头在游戏领域展开了一场激烈的较量。今...
安卓手机没有系统更,揭秘潜在风... 你有没有发现,现在安卓手机的品牌和型号真是五花八门,让人挑花了眼。不过,你知道吗?尽管市面上安卓手机...
充值宝带安卓系统,安卓系统下的... 你有没有发现,最近手机上的一款充值宝APP,在安卓系统上可是火得一塌糊涂呢!这不,今天就来给你好好扒...
安卓系统8.0镜像下载,轻松打... 你有没有想过,想要给你的安卓手机升级到最新的系统,却不知道从哪里下载那个神秘的安卓系统8.0镜像呢?...
安卓系统修改大全,全方位修改大... 你有没有想过,你的安卓手机其实是个大宝藏,里面藏着无数可以让你手机焕然一新的秘密?没错,今天就要来个...