【C语言进阶】文件操作:文件的打开与文件的读写以及文本文件和二进制文件

目录

1、为什么使用文件

2、什么是文件 

2.1 程序文件

2.2 数据文件 

2.3 文件名

3、文件的打开和关闭 

3.1文件指针 

3.2文件的打开与关闭 

4、文件的顺序读写 

4.1 几个函数的区别

5、文件随机读写 

 5.1 fseek

5.2 ftell 

5.3 rewind 

6、文本文件和二进制文件 

7、文件读取结束的判定 

 7.1 被错误使用的feof

8、文件缓冲区



1、为什么使用文件

我们学习结构体时,写了静态通信录,可以在通讯录中增加、删除数据,此时数据是存放在内存中,当程序退出的时候,数据又要重新录入,当程序退出时,通讯录中的数据就不存在了,等下次运行通讯录,数据又要重新录入。我们想既然是通讯录就应该把信息记录下来,只有我们删除数据时,数据才不复存在。

使用文件主要是为了数据持久化、用户交互和数据交换。文件可以存储数据,即使程序关闭或计算机重启,数据也不会丢失。同时,文件也是程序与用户之间以及不同程序之间交换信息的重要媒介。

2、什么是文件 

磁盘上的文件就是文件,但在程序设计中,我们一般只谈程序文件和数据文件

2.1 程序文件

包括源程序文件(后缀为.c),目标文件(Windows环境后缀为.obj),可执行程序(Windows环境后缀为.exe)

2.2 数据文件 

 文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件

这篇文章所要讨论的是数据文件。以前所处理的数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显示器上。其实有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使用,这里处理的就是磁盘文件。

2.3 文件名

一个文件要有一个唯一的文件标识,以便用户识别和引用。文件名包含3部分:文件路径+文件名主干+文件后缀

比如:c:\code\test.txt

3、文件的打开和关闭 

3.1文件指针 

 缓冲文件系统中,关键的概念是“文件类型指针”,简称"文件指针“。

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

//文件类型声明
typedef struct _iobuf
{char *_ptr;int _cnt;char *_base;int _flag;int _file;int _charbuf;int _bufsiz;char *_temfname;
}FILE;

不同的C编译器的FILE类型包含的内容不完全相同,但基本差不多。

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

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

FILE* pf;//文件指针变量 

定义pf是一个指向FILE类型数据的指针变量。可以使用pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它相关联的文件

3.2文件的打开与关闭 

文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。

在编写程序的时候,在打开文件的同时,都会返回一个FILE*  的指针变量指向该文件,也相当于建立了指针和文件的关系。

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

//打开文件
FILE* fopen(const char* filename, const char* mode);//filename是文件名,mode是文件打开模式(读或写)
//关闭文件
int fclose(FILE* stream);

文件的使用: 

#include<stdio.h>
#include<errno.h>
#include<string.h>
int main()
{FILE* pf=fopen("test.txt", "r");//在对应路径创建文件名为“text”,系统默认扩展名为txtif (pf == NULL){printf("%s\n", strerror(errno));return 1;}//读文件//......//关闭文件fclose(pf);pf = NULL;return 0;
}
文件使用方式含义如果指定文件不存在
"r"(只读)为了输入数据打开一个已经存在的文本文件出错
"w"(只写)为了输出数据打开一个文本文件建立一个新文件
"a"(追加)向文本文件尾添加数据建立一个新文件
"rb"(只读)为了输入数据打开一个二进制文本出错
"wb"(只写)为了输出数据打开一个二进制文本建立一个新文件
"ab"(追加)向一个二进制文件尾添加数据出错
"r+"(读写)为了读和写打开一个文本文件出错
"w+"(读写)为了读和写建立一个文本文件建立一个新文件
"a+"(读写)打开一个文件,在文件尾进行读写建立一个新文件
"rb+"(读写)为了读和写打开一个二进制文件出错
"wb+"(读写)为了读和写新建一个二进制文件建立一个新文件
"ab+"(读写)为了追加和读新建一个二级制文本建立一个新文件

4、文件的顺序读写 

功能函数名适用场景
字符输入函数fgetc所有输入流
字符输出函数fputc所有输出流
文本行输入函数fgets所有输入流
文本行输出函数fputs所有输出流
格式化输入函数fscanf所有输入流
格式化输出函数fprintf所有输出流
二进制输入fread文件
二进制输出fwrite文件
/举个栗子
#include<stdio.h>
#include<errno.h>
#include<string.h>
int main()
{FILE* pf = fopen("text.txt.txt", "w");if (pf == NULL){printf("%s\n", strerror(errno));return 1;}//写文件char i = 0;for (i = 'a'; i <= 'z'; i++){fputc(i, pf);}//关闭文件fclose(pf);pf == NULL;return 0;
}

其他函数就不在这里一一举例了,大家可以在cplusplus.com官网查看函数的使用方法 

 注意:如果文件里面有原始数据,我们在写文件时会把原始数据给覆盖掉,如果不想销毁就改成追加。

4.1 几个函数的区别

 scanf:是针对标准输入的的格式化输入语句

 printf:是针对标准输出的的格式化输出语句

 fscanf:是针对所有输入流的格式化输入语句

 fprintf: 是针对所有输出流的格式化输出语句

 sscanf:从一个字符串中转换出格式化的数据

 sprintf:是把一个格式化的数据转换成字符串

//sprintf
//int sprintf(char* str, const char* format, ...);
//将格式化数据写入字符串
struct S
{char name[20];int age;float score;
};
int main()
{struct S s = { "张三",20,50.5f };char buffer[100] = { 0 };sprintf(buffer, "%s %d %f\n", s.name, s.age, s.score);printf("%s\n", buffer);//字符串打印(此时已经转化为字符串)//sscanf//int sscanf(const char* s, const char* format, ...);//从字符串中读取格式化数据sscanf(buffer, "%s %d %f", s.name, &(s.age), &(s.score));printf("%s %d %lf\n", s.name, s.age, s.score);return 0;
}

5、文件随机读写 

 5.1 fseek

 根据文件指针的位置和偏移量来定位文件指针

int fseek ( FILE * stream, long int offset, int origin );

//文件中放的是abcdef
int main()
{FILE* pf = fopen("text.txt.txt", "r");if (pf == NULL){printf("%s\n", strerror(errno));return 1;}//定位文件指针fseek(pf, 2, SEEK_SET);int ch = fgetc(pf);printf("%c\n", ch);//关闭文件fclose(pf);pf == NULL;return 0;
}

5.2 ftell 

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

long int ftell (FILE* sream);

int main()
{FILE* pf = fopen("text.txt.txt", "r");if (pf == NULL){printf("%s\n", strerror(errno));return 1;}//定位文件指针fseek(pf, 2, SEEK_SET);int ch = fgetc(pf);printf("%c\n", ch);printf("%d\n", ftell(pf));//关闭文件fclose(pf);pf == NULL;return 0;
}

5.3 rewind 

 让文件指针的位置回到文件的起始位置

void rewind(FILE* stream);

int main()
{FILE* pf = fopen("text.txt.txt", "r");if (pf == NULL){printf("%s\n", strerror(errno));return 1;}//定位文件指针fseek(pf, 2, SEEK_SET);int ch = fgetc(pf);printf("%c\n", ch);printf("%d\n", ftell(pf));rewind(pf);ch = fgetc(pf);printf("%c\n", ch);fclose(pf);pf == NULL;return 0;
}

6、文本文件和二进制文件 

根据数据的组织形式,数据文件被称为文本文件二进制文件。根据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件;如果要求在外存上以ASCII码值的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件

一个数据在内存中是如何存储的?

字符一律以ASCII码值的形式存储,数值型数据既可以用ASCII形式存储,也可以用二进制形式存储;如果有整数10000,以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而二进制形式输出,则在磁盘上只占4个字节

int main()
{int a = 100000;FILE* pf=fopen("text.txt.txt", "wb");if (pf == NULL){perror("fopen");return 1;}fwrite(&a, 4, 1, pf);fclose(pf);pf = NULL;return 0;
}

7、文件读取结束的判定 

 7.1 被错误使用的feof

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

1、文本文件读取是否结束,判断返回值是否为EOF(fgetc)或NULL(fgets)

2、二进制文件读取结束判断,判断返回值是否小于实际要读的个数 

8、文件缓冲区 

ANSIC标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”。从内存此磁盘输出数据会先送到内存中的缓冲区,装满缓冲区才一起送到磁盘上。如果从从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。 

#include<stdio.h>
#include<Windows.h>
int main()
{FILE* pf = fopen("test.txt.txt", "w");fputs("abcdef", pf);printf("睡眠10秒-已经写数据,打开test.txt.txt文件,发现文件没有内容\n");Sleep(10000);printf("刷新缓冲区\n");fflush(pf);//刷新缓冲区时,才将缓冲区的数据写到文件printf("再睡眠10秒-此时再次打开test.txt.txt文件,文件有内容了\n");Sleep(10000);fclose(pf);//关闭文件时也会刷新缓冲区pf = NULL;return 0;
}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/20692.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springboot+vue+mybatis超市管理-简单版+PPT+论文+讲解+售后

使用旧方法对超市信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在超市信息的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。 这次开发的小型超市管理系统有管理员&…

探索DIYGW可视化开发工具:提升UniApp项目效率与质量的新途径

一、引言 在快速迭代和不断创新的移动应用开发领域中&#xff0c;开发者们常常面临着一个共同的挑战&#xff1a;如何在保证开发质量的同时&#xff0c;缩短开发周期。近期&#xff0c;一款名为DIYGW的可视化开发工具进入了我们的视野&#xff0c;它以其独特的拖拽式开发方式和…

算法题-给定一个日期,输出星期几

目录 给定日期&#xff0c;输出对应是星期几 测试结果 如1900年 5月6日是星期三&#xff0c;计算给的日期是星期几 给定日期&#xff0c;输出对应是星期几 #include <stdio.h> #include <stdlib.h> #include <string.h>int main() {char input[100];int d…

如何被谷歌收录?

最简单的方法就是提交网站给谷歌&#xff0c;但这种方法可操作空间不大&#xff0c;一天一般也就只有十条左右的链接可以提交&#xff0c;对于一些大网站来说&#xff0c;这种方法显然不适用&#xff0c;这时候GPC爬虫池的好处就体现了&#xff0c;GPC爬虫池对希望提升Google搜…

Deepin Linux 深度 V23 beige 官方源及换镜像源方法。

Deepin Linux 深度 V23 英文版本号&#xff1a;beige 谁起的烂名字。。。。。。 1. 打开文件管理器&#xff0c;在apt文件夹点右键&#xff08;以管理员身份打开&#xff09;&#xff0c; 2. 输入你的登录密码&#xff0c;以便打开文件夹&#xff08;管理员权限&#xff09;。…

【MySQL数据库】索引与事务

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【MySQL】探秘&#xff1a;数据库世界的瑞士军刀 目录 &#x1f5f3;️一.索引 &#x1f4ee;1.工作原理 &#x1f4ec;2.类型 &#x1f4ed;3.作用 &#x1f4ea;4.优缺点 &#x1f4eb;5.使用…

【Modelground】个人AI产品MVP迭代平台(2)——网站从0-1部署教程

文章目录 1.选购一台云服务器2. 购买域名3. 通过nginx部署静态网站4. 通过gitee在云服务器拉取代码5. ICP备案总结 1.选购一台云服务器 目前阿里云在促销&#xff0c;一台2核2GB内存3Mbps宽带的云服务器&#xff0c;一年只需要99元&#xff0c;学生更便宜&#xff0c;我认为这…

Java——处理键盘输入

在Java中&#xff0c;可以使用多种方式来处理键盘输入。最常用的一种方法是使用 Scanner 类&#xff0c;它位于 java.util 包中。 一、使用 Scanner 类处理键盘输入 1、具体操作步骤 1&#xff09;导入 Scanner 类 在开始编写代码之前&#xff0c;需要导入 java.util.Scann…

【TB作品】MSP430F5529,单片机,电子秒表,秒表

硬件 MSP430F5529开发板7针0.96寸OLED /* OLED引脚分配 绿色板子DO(SCLK)------P4.3D1(DATA)------P4.0RES-----------P3.7DC------------P8.2CS------------P8.1 */ 程序功能 该程序是一个用C语言编写的&#xff0c;用于msp430f5529微控制器上的简单电子秒表应用。它使用…

1882java密室逃脱管理系统 Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java密室逃脱管理系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助采用了java设计&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统采用web模式&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&…

7.2 Go 使用error类型

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

数论1---整除

概念与基本性质就不说了 例题1&#xff1a;已知a|n&#xff0c;b|n.且axby1,求证&#xff1a;ab|n 即&#xff1a; 所以&#xff1a;ab|n 例题2&#xff1a;设m是一个大于2的正整数&#xff0c;证明&#xff1a;对于任意正整数n&#xff0c;都有 由于我不想打公式了直接拍照…

react-native 默认停用 flipper 通知

react-native 0.74 默认停用 flipper &#xff0c;但仍然可以手动安装 flipper 官方声明文档 英语好的可以直接阅读。 integration with React Native will no longer be enabled 原因 增加编译时间有时候会有连接问题升级会导致不能使用 之后调试推荐 我们建议团队使用 A…

【Qt知识】Qt窗口坐标系

Qt的窗口坐标体系遵循标准的计算机图形坐标系统规则 Qt窗口坐标体系特点 坐标原点&#xff1a;窗口坐标体系的原点位于窗口的左上角&#xff0c;即坐标(0, 0)位置。 轴方向&#xff1a; X轴&#xff1a;向右为正方向&#xff0c;随着X坐标值的增加&#xff0c;元素在窗口中从…

opencv-python(二)

马赛克 img cv2.imread(./bao.jpeg)print(img.shape)img2 cv2.resize(img,(35,23))img3 cv2.resize(img2,(900,666))cv2.imshow(bao,img3)cv2.waitKey(0)cv2.destroyAllWindows()img2 cv2.resize(img, (90,66))img3 np.repeat(img2, 10, axis 0) # 重复行img4 np.repeat(…

数据结构---时间复杂度与空间复杂度

文章目录 1. 知识背景2. 什么是时间复杂度&#xff1f;3. 空间复杂度4 .大O渐进表示法&#xff1a;对于一些算法的时间复杂度存在最好&#xff0c;最坏&#xff0c;平均的情况&#xff1a; 5. 常见的时间复杂度举例总结&#xff1a;6. 空间复杂度的举例与总结&#xff1a;总结&…

腾讯 InstantMesh,单图生成 3D 模型,10 秒内完成,性能超越 SOTA

前言 近年来&#xff0c;3D 内容创作在游戏、动画、虚拟现实等领域发挥着越来越重要的作用。然而&#xff0c;传统的 3D 模型制作流程繁琐&#xff0c;需要专业人员花费大量时间和精力。为了简化 3D 内容创作流程&#xff0c;腾讯 ARC 实验室推出了 InstantMesh&#xff0c;一…

开源代码分享(32)-基于改进多目标灰狼算法的冷热电联供型微电网运行优化

参考文献&#xff1a; [1]戚艳,尚学军,聂靖宇,等.基于改进多目标灰狼算法的冷热电联供型微电网运行优化[J].电测与仪表,2022,59(06):12-1952.DOI:10.19753/j.issn1001-1390.2022.06.002. 1.问题背景 针对冷热电联供型微电网运行调度的优化问题&#xff0c;为实现节能减排的目…

prometheus-alert使用

说明&#xff1a;本文介绍一款可接管alertmanager报警&#xff0c;简化alertmanager配置的组件prometheus-alert。可以将prometheus检测到的异常指标&#xff0c;通过alertmanager转给prometheus-alert&#xff0c;由prometheus-alert通知到各个应用。 如下&#xff1a; 上图来…

# linux 系统下,使用 docker 启动 mysql 后,通过 sqlyog 连接 mysql 报“错误号码2058“

linux 系统下&#xff0c;使用 docker 启动 mysql 后&#xff0c;通过 sqlyog 连接 mysql 报“错误号码2058“ 一、错误描述&#xff1a; 在 ubuntu 系统上&#xff0c;刚安装的 docker 启动 mysql 后&#xff0c;想通过图形界面 SQLyong 等工具连接 mysql 出现“错误号码2058…