C进阶:文件的基础操作
创始人
2024-05-13 01:26:30
0

本文主要讲解文件基础操作的知识。

目录

一.文件指针

二.文件的打开和关闭

1.文件的打开

 打开文件我们需要使用到 fopen 函数;

注意(文件扩展名):

2.文件的关闭

三.文件的读写

1.读与写,输出与输入的概念

​编辑

 2.流的概念

3.字符的读与写  fgetc 与 fputc

实例:

 4.文本行的读与写  fgets 与 fputs 

实例:

5.二进制的读与写   fread 与 fwrite

实例:

四.文件结束的判定

1.被错误使用的 feof 

2.一些判断文件结束的总结

五.文件缓冲区


一.文件指针

1.缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”;
2.每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等);

3.这些信息是保存在一个结构体变量中的。该结构体类型是有系统声明的,取名FILE。

下面是在 vs2013编译环境提供的 stdio.h 头文件中有以下的文件类型申明:

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

不同的编译器结构体的内容可能有些不一样,但都大同小异;

每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,使用者不必关心细节。
一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。

下面创建一个文件指针变量:

1.定义pf是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变量);

2.通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它关联的文件。

例如:

 


二.文件的打开和关闭

1.文件的打开

 打开文件我们需要使用到 fopen 函数;

让我们看看 fopen 在库函数中的声明:

1.需要头文件 ;

2.参数 const char *filename : 要打开的文件的文件名 ;

3.参数 const char *mode :表示要打开的模式;

4.返回值:返回一个文件指针,若文件打开失败则返回一个空指针

注意(文件扩展名):

有些小伙伴们打开文件的时候,认为自己的文件名是正确的,但编译器却显示没有这个文件,这个时候不要质疑电脑,电脑是不会出错的,遇到这种情况我们应检查文件管理器的文件扩展名是否开启,如果没有打开那打开就行了,你会发现有些文件名称发生了变化;

详情如图:

 文件打开模式:


 

2.文件的关闭

关闭文件需要使用到函数 fclose  ;

下面来看看 fclose 在库函数中的声明:

1.参数 FILE *stream : 这是指向 FILE 对象的指针,该 FILE 对象指定了要被关闭的流;

2.返回值:若文件关闭成功,则返回0

                 若文件关闭失败,则返回EOF

实例:

int main()
{FILE* pf = fopen("test.txt", "w");   //以只写的方式打开文件if (pf == NULL)   //判断文件是否打开成功{perror("fopen");  //若打开失败,则显示错误信息return 0;}//写文件//.......//关闭文件fclose(pf);   pf = NULL;  //将文件指针置空,防止野指针的使用return 0;
}

三.文件的读写

1.读与写,输出与输入的概念

 

 2.流的概念

 可以看到流其实是一个极其抽象的概念,我们可以把它理解成C程序与外部设备进行交流的一个媒介;

3.字符的读与写  fgetc 与 fputc

字符的读取函数 fgetc :

1.参数 FILE *stream :这是指向 FILE 对象的指针,该 FILE 对象标识了要在上面执行操作的流;

2.返回值:该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生读错误,则返回 EOF

字符的写入函数 fputc

1.描述 :把参数 char 指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动;

2.参数 int char :这是要被写入的字符。该字符以其ASCII 值进行传递;

3.参数 FILE *stream : 这是指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符的流;

4.返回值:该函数以无符号 char 强制转换为 int 的形式(即字符的ASCII值)返回写入的字符,如果发生错误则返回 EOF。

实例:

int main()
{FILE* pf = fopen("test.txt", "w");  //以只写的方式打开文件if (pf == NULL){perror("fopen");return 0;}char ch = 0;for (ch = 'a'; ch <= 'z'; ch++)   //向文件写入26个小写英文字母{fputc(ch, pf);}fclose(pf);pf = NULL;FILE *pfread = fopen("test.txt", "r");  //以只读的方式打开文件if (pfread == NULL){perror("fopen");return 0;}while (ch!= EOF)   //判断是否读取到文件末尾{ch = fgetc(pfread);   //从文件中读取字符printf("%c", ch);   //打印读取道德字符}fclose(pfread);pfread = NULL;return 0;
}

打印结果:


 4.文本行的读与写  fgets 与 fputs 

  文本行的读取 fgets

1.描述: 从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。

当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定;

2.参数 char *str :这是指向一个字符数组的指针,该数组存储了要读取的字符串;

3.参数 int n : 这是要读取的最大字符数(包括最后的空字符)。通常是使用以 str 传递的数组长度;

4.参数 FILE *stream :这是指向 FILE 对象的指针,该 FILE 对象标识了要从中读取字符的流;

5.返回值:如果成功,该函数返回相同的 str 参数

如果到达文件末尾或者没有读取到任何字符,str 的内容保持不变,并返回一个空指针

如果发生错误,返回一个空指针

文本行的写入 fputs 

1.描述:把字符串写入到指定的流 stream 中,但不包括 '\0'

2.参数  const char *str  : 这是一个数组,包含了要写入的以 '\0' 终止的字符序列;

3.参数  FILE *stream : 这是指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符串的流;

4.返回值:该函数返回一个非负值,如果发生错误则返回 EOF

实例:

int main()
{char str[] = "abcdefg";FILE* pf = fopen("test.txt", "w");   //以只写的方式打开文件if (pf == NULL)  //判断是否打开成功{perror("fopen");return 0;}fputs(str, pf);  //向文件中写入 strfclose(pf);pf = NULL;FILE* pfread = fopen("test.txt", "r");  //以只读的方式打开文件if (pfread == NULL)  //判断时候打开成功{perror("fopen");return 0;}char tmp[20] = { 0 };printf("%s\n", fgets(tmp, 20, pfread));   //将读取到的字符串存入 tmp 中,并打印fclose(pfread);  //关闭文件pfread = NULL;return 0;}

 打印结果:

5.二进制的读与写   fread 与 fwrite

二进制的读取  fread  :

1.描述:从给定流 stream 读取数据到 ptr 所指向的数组中;

2.参数  void *ptr :这是指向带有最小尺寸 size*nmemb 字节的内存块的指针;

3.参数  size_t size :这是要读取的每个元素的大小,以字节为单位

4.参数  size_t nmemb :这是元素的个数,每个元素的大小为 size 字节;

5.参数  FILE *stream : 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输入流;

6.返回值 :成功读取的元素总数会以 size_t 对象返回,size_t 对象是一个整型数据类型。如果总数与 nmemb 参数不同,则可能发生了一个错误或者到达了文件末尾,即如果返回值小于元素个数 ,则发生了错误或读到文件末尾。

二进制的写入  fwrite

描述:把 ptr 所指向的数组中的数据写入到给定流 stream 中;

各参数的意思fread  一致,只不过是把读取换成了写入

返回值:如果成功,该函数返回一个 size_t 对象,表示元素的总数,该对象是一个整型数据类型。如果该数字与 nmemb 参数不同,则会显示一个错误。

实例:

int main()
{int a = 10000;FILE* pfwrite = fopen("test.bin", "wb");  //以二进制写的方式打开文件if (pfwrite == NULL){perror("fopen");return 0;}fwrite(&a, sizeof(int), 1, pfwrite);  //写入文件fclose(pfwrite);pfwrite = NULL;FILE* pfread = fopen("test.bin", "rb");   //以二进制读的方式打开文件if (pfread == NULL){perror("fopen");return 0;}int b = 0;fread(&b, sizeof(int), 1, pfread);  //读取文件printf("%d\n", b);fclose(pfread);pfread = NULL;return 0;
}

 

程序运行起来成功打印了10000,但当我们打开记事本看这个文件时却是一个看不懂的符号;

这是因为我们是以二进制的方式写的文件,所以才会显示这样,我们可以用可以查看二进制文件的软件查看,例如 vs2022 就可以查看二进制文件;

 

四.文件结束的判定

1.被错误使用的 feof 

首先牢记:在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束。
而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。

所以 feof 是用来判断文件是什么原因结束的。

2.一些判断文件结束的总结

1. 文本文件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )
       例如:
                fgetc 判断是否为
EOF .
                fgets 判断返回值是否为 NULL .
2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
       例如:
                fread判断
返回值是否小于实际要读的个数。

例子:

#include 
#include 
int main()
{int c; // 注意:int,非char,要求处理EOFFILE* fp = fopen("test.txt", "r");if(!fp) {perror("File opening failed");return EXIT_FAILURE;}//fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOFwhile ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环{putchar(c);}//判断是什么原因结束的if (ferror(fp))puts("I/O error when reading");else if (feof(fp))puts("End of file reached successfully");fclose(fp);fp=NULL;return 0;
}

五.文件缓冲区

       ANSIC 标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”。

      从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。

      如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。

      缓冲区的大小根据C编译系统决定的。

 实例:

#include 
#include 
//VS2013 WIN10环境测试
int main()
{FILE*pf = fopen("test.txt", "w");fputs("abcdef", pf);//先将代码放在输出缓冲区printf("睡眠10秒-已经写数据了,打开test.txt文件,发现文件没有内容\n");Sleep(10000);printf("刷新缓冲区\n");fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘)//注:fflush 在高版本的VS上不能使用了printf("再睡眠10秒-此时,再次打开test.txt文件,文件有内容了\n");Sleep(10000);fclose(pf);//注:fclose在关闭文件的时候,也会刷新缓冲区pf = NULL;return 0;
}

结论:

     因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。
     如果不做,可能导致读写文件的问题。


🐬🤖本篇文章到此就结束了,若有错我或是建议的话,欢迎小伙伴们指出;🕊️👻

😄😆希望小伙伴们能支持支持博主啊,你们的支持对我很重要哦;🥰🤩

😍😁谢谢你的阅读。😸😼

 

相关内容

热门资讯

常用商务英语口语   商务英语是以适应职场生活的语言要求为目的,内容涉及到商务活动的方方面面。下面是小编收集的常用商务...
六年级上册英语第一单元练习题   一、根据要求写单词。  1.dry(反义词)__________________  2.writ...
复活节英文怎么说 复活节英文怎么说?复活节的英语翻译是什么?复活节:Easter;"Easter,anniversar...
2008年北京奥运会主题曲 2008年北京奥运会(第29届夏季奥林匹克运动会),2008年8月8日到2008年8月24日在中华人...
英语道歉信 英语道歉信15篇  在日常生活中,道歉信的使用频率越来越高,通过道歉信,我们可以更好地解释事情发生的...
六年级英语专题训练(连词成句... 六年级英语专题训练(连词成句30题)  1. have,playhouse,many,I,toy,i...
上班迟到情况说明英语   每个人都或多或少的迟到过那么几次,因为各种原因,可能生病,可能因为交通堵车,可能是因为天气冷,有...
小学英语教学论文 小学英语教学论文范文  引导语:英语教育一直都是每个家长所器重的,那么有关小学英语教学论文要怎么写呢...
英语口语学习必看的方法技巧 英语口语学习必看的方法技巧如何才能说流利的英语? 说外语时,我们主要应做到四件事:理解、回答、提问、...
四级英语作文选:Birth ... 四级英语作文范文选:Birth controlSince the Chinese Governmen...
金融专业英语面试自我介绍 金融专业英语面试自我介绍3篇  金融专业的学生面试时,面试官要求用英语做自我介绍该怎么说。下面是小编...
我的李老师走了四年级英语日记... 我的李老师走了四年级英语日记带翻译  我上了五个学期的小学却换了六任老师,李老师是带我们班最长的语文...
小学三年级英语日记带翻译捡玉... 小学三年级英语日记带翻译捡玉米  今天,我和妈妈去外婆家,外婆家有刚剥的`玉米棒上带有玉米籽,好大的...
七年级英语优秀教学设计 七年级英语优秀教学设计  作为一位兢兢业业的人民教师,常常要写一份优秀的教学设计,教学设计是把教学原...
我的英语老师作文 我的英语老师作文(通用21篇)  在日常生活或是工作学习中,大家都有写作文的经历,对作文很是熟悉吧,...
英语老师教学经验总结 英语老师教学经验总结(通用19篇)  总结是指社会团体、企业单位和个人对某一阶段的学习、工作或其完成...
初一英语暑假作业答案 初一英语暑假作业答案  英语练习一(基础训练)第一题1.D2.H3.E4.F5.I6.A7.J8.C...
大学生的英语演讲稿 大学生的英语演讲稿范文(精选10篇)  使用正确的写作思路书写演讲稿会更加事半功倍。在现实社会中,越...
VOA美国之音英语学习网址 VOA美国之音英语学习推荐网址 美国之音网站已经成为语言学习最重要的资源站点,在互联网上还有若干网站...
商务英语期末试卷 Part I Term Translation (20%)Section A: Translate ...