C语言详解文件操作

目录

什么是文件?


为什么使用文件?


程序文件和数据文件、文本文件和二进制文件

1.程序文件和数据文件

1.1程序文件

1.2数据文件

2.文本文件和二进制文件


文件的打开和关闭(流、标准流、文件指针和文件的打开与关闭)

1.流和标准流

1.1:流

1.2:标准流

2.文件指针

3.文件的打开和关闭

例:"w"——只写(从文件输出数据)

关闭文件


文件的顺序读写和随机读写

1.文件的顺序读写

1.1:顺序读写的函数介绍

1.2:fputc函数

1.3:fgetc函数

1.4:fputs和fgets函数

对比三组函数

2.文件的随机读写

2.1:fseek

2.2:ftell 

2.3:rewind


文件读取结束的判定

1.feof

2.文件读取结束的判定


文件缓冲区


什么是文件?

磁盘(硬盘)上的文件是文件。

可能有点抽象,举个例子,如图:

图中所有的文件包括文件夹都是文件。

而为了使用文件,自然也需要文件名来让我们进行识别和引用。

文件名包含三部分:文件路径 + 文件名主干 + 文件后缀

例如:c:\code\test.txt

为什么使用文件?

首先要知道,我们写的程序的数据是存储在电脑的内存中的,如果没有文件,程序退出内存回收,数据就丢失了,等再次运行程序就无法看到上次程序的数据。

文件可以将数据进行持久化保存

因此如果要将数据进行持久化的保存,我们可以使用文件。

程序文件和数据文件、文本文件和二进制文件

1.程序文件和数据文件

在程序设计中,我们一般谈的文件有两种(从文件功能的角度来分类的):程序文件和数据文件

1.1程序文件

程序文件(按我的理解)口语化一点的讲就是我们写的代码那些所产生的文件。——

比如我们写代码就是在.c文件写的,编译后产生的就是.obj(目标)文件,链接后就是.exe文件。

都是我们编写的代码所产生的文件(或者在文件中编写的代码)

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

1.2数据文件

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

我们之前基本都是以程序文件的形式运行代码的,而本章主要讨论的就是数据文件了。

2.文本文件和二进制文件

根据数据的组织形式(按内容分),数据文件又被称为文本文件二进制文件

数据在内存中以二进制的形式存储,如果不加转换的输出到外存的文件中(也就是直接输出了),就是二进制文件

如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件。

文件的打开和关闭(流、标准流、文件指针和文件的打开与关闭)

1.流和标准流

1.1:流

当我们写个程序要输出到外部设备上,或者要从外部设备读取数据时,外部设备不同,输入输出操作自然也可能不同,因此为了方便我们操作,就产生了流。

C程序针对文件、画面、键盘等的数据输入输出都是通过对流操作的。

我们可以把流当作中介,一般当我们要向流里写数据,或者从流中读取数据时,都是打开流然后进行操作。

有小伙伴可能会问了,我们这题目明明是“题目的打开和关闭”,为什么要突然讲流和标准流呢?

其实不难想到,文件我们上文讲过是用来将数据进行持久化保存的——也就是说,文件里面放的也是数据,而文件的打开和关闭即文件的使用文件的使用不管是读取还是输出数据,都要经过我们的流来进行数据的输入输出,因此流是我们学习文件使用的基础,所以先对流进行讲解,下文中的标准流、文件指针等也是同理。

1.2:标准流

我们上文中讲了“C程序针对文件、画面、键盘等的数据输入输出都是通过对流操作的。”,可我们从键盘输入数据并从屏幕上输出数据时并没有打开流,直接使用scanf、printf等函数就可以直接进行输入输出操作了,这是为什么呢?——

这都是因为C程序在启动时已经默认打开了三个流

  • stdin - 标准输入流 ,在大多数的环境中从键盘输入,scanf函数就是从标准输入流中读取数据。
  • stdout - 标准输出流,大多数环境中输出至显示器页面,printf函数就是将信息输出到标准输出流中。
  • stderr - 标准错误流,大多数环境中输出到显示器页面。

stdin、stdout和stderr三个流的类型都是:FILE*,通常称为文件指针

C语言中,就是通过FILE* 的文件指针来维护流的各种操作的。

2.文件指针

其实是叫“文件类型指针”,简称文件指针

文件存放着数据,文件被使用时本身也是数据,因此被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件名、文件位置等)。

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

如下图:

一般都是通过一个FILE的指针来维护这个FILE结构的变量。(也就是通过一个指向FILE的指针来对与FILE有关联的文件进行访问)。

3.文件的打开和关闭

当我们开始对文件打开与关闭时应该就是要使用(读写)我们的文件了——使用文件的步骤可以分三步:

  1. 打开文件(其实就是打开流)
  2. 读/写文件
  3. 关闭文件(其实就是关闭流)

ANSI C规定使用fopen函数来打开文件fclose函数来关闭文件

如图分别为在cplusplus中找到的两个函数的介绍:

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

mode表示文件的打开方式(即读/写/······)。下面都是文件的打开方式:

例:"w"——只写(从文件输出数据)

假设我们此时要写一个文件test.txt,如图:

但此时我们的文件夹并没有text.txt这个文件,此时的文件夹如下图:

但是当我们运行代码后,就在文件夹中产生了一个text.txt文件,如下图示:

关闭文件

前文有讲过:我们关闭文件要用fclose函数,但是关闭后我们还需要手动置为空指针

如图:

此时我们经过调试,可以看到,指针pf经fclose函数关闭后,还是有地址,只是不指向文件了,因此此时的pf指针是野指针,所以我们要手动将其置空指针。

文件的顺序读写和随机读写

1.文件的顺序读写
1.1:顺序读写的函数介绍

顺序读写的函数介绍如下图:​​​​​​​

上图中的适用于所有输入流一般指的是适用与标准输入流和其他输入流(如文件输入流),

适用于所有输出流也同理(标准输出和其他输出)。

1.2:fputc函数

由上图我们可以知道,fputc为字符输出函数,函数形式如下(函数的具体功能可以自行前往fputc - C++ Reference (cplusplus.com) 查看):​​​​​​​

函数有了解之后我们就接着按三板斧来进行实现了,函数实现如下:

int main()
{//1.打开文件FILE* pf = fopen("text.txt", "w");if (pf == NULL){perror(fopen);return 1;}//2.使用(写)文件fputc('a', pf);fputc('b', pf);fputc('c', pf);fputc('d', pf);fputc('e', pf);//3.关闭文件fclose(pf);pf = NULL;return 0;
}

运行后我们就已经将abcde写入了文件text.txt中。

原本该文件是我们在上文中新建的内容为空,此时内容为"abcde"如下图所示:

1.3:fgetc函数

fgetc为字符输入函数,函数形式如下:

函数实现效果如下:

因为上文中我们已经往文件text.txt中写入了abcde,因此现在读四次读出来的是abcd。

1.4:fputs和fgets函数

这两个函数和上文刚刚讲的fputc和fgetc函数类似,此处就直接举例说明(fputs函数)了,如图:

如上图,fputs是进行写字符串操作的,将字符串写入pf指向的内容(此图指向的为text.txt文件中)

但是写字符串是连续的,如果希望换行需要自己在字符串末尾加\n.

fgets函数就相对复杂一点点,函数形式如下图:

此时我们text.txt文档内的放置内容为abcdef

fgets示例如下:



对比三组函数

scanf/printf —— 针对标准输入/输出流的 格式化 输入/输出函数

fscanf/fprintf —— 针对所有输入/输出流的 格式化 输入/输出函数

sscanf/sprintf —— 从字符串中读取格式化的数据 / 将格式化的数据写到字符串中



后面的四个函数就不过多赘述了,详细功能可以自行在cplusplus网址

(Reference - C++ Reference (cplusplus.com))中查找

2.文件的随机读写
2.1:fseek

根据文件指针的位置和偏移量来定位文件指针(文件内容的光标)

文件的第三个参数(起始位置)如下:

示例:

int main()
{//1.打开文件FILE* pf = fopen("text.txt", "wb");if (pf == NULL){perror(fopen);return 1;}//2.使用(写)文件fputs("This is an apple.", pf);fseek(pf, 9, SEEK_SET);fputs(" sam", pf);//3.关闭文件fclose(pf);pf = NULL;return 0;
}

2.2:ftell 

返回文件指针相较于起始位置的偏移量,形式如下:

这个就比较好理解了,我们直接上示例:

2.3:rewind

让文件指针的位置回到起点位置,形式如下:

我们在上图示例代码的基础上,再加入rewind观察,如下图所示:

文件读取结束的判定

1.feof

在文件读取过程中,不能用feof直接判断文件读取是否结束

feof是在当文件读取结束的时候,判断读取结束的原因是否是:遇到文件尾结束(也就是是否是正常读完的)。

2.文件读取结束的判定
  • 判定文本文件读取是否结束时

判断返回值是否为EOF(fgetc),

或NULL(fgets)。

  • 判定二进制文件时

判定返回值是否小于实际要读的个数(fread)。

文件缓冲区

ANSIC标准采用“缓冲文件系统”处理数据文件的,

缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”。

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

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

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

图示如下:

正是因为缓冲区的存在,所以我们在文件操作结束后才需要关闭文件,如果没有关闭可能导致读写文件的问题。



创作不易,如果觉得作者写的还行的话给个免费的三连吧亲🌹🌹

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

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

相关文章

有点好玩的python运维脚本

python运维脚本 1. 常用端口扫描2. 文件整理 1. 常用端口扫描 在计算机网络中,端口是一个通信端点,允许不同的进程或服务通过网络连接和交换数据。端口通过数值来标识,并与特定的协议相关联。未采取适当安全措施而保持端口开放,可…

InternLM Xtuner Qlora 微调

Xtuner 简介 XTuner 是由上海人工智能实验室开发的一款低成本大模型训练工具箱。它以高效、灵活和全能的特性,成为轻量化大模型微调的理想选择。借助 XTuner,用户仅需 8GB 显存即可对 InternLM2-7B 模型进行微调,从而定制出独一无二的 AI 助手…

C++~~期末复习题目讲解---lijiajia版本

目录 1.类和对象 (3)创建对象的个数 (3)全局变量,局部变量 (4)构造函数的执行次数 (5)静态动态析构和构造顺序 (6)初始化顺序和声明顺序 &a…

安装systemd-bootchart

要安装systemd-bootchart,你可以按照以下步骤进行: 步骤一:更新软件包列表 首先,打开终端并更新你的软件包列表,以确保你拥有最新的可用软件包信息。运行以下命令: sudo apt update步骤二:安…

Git使用总结(git使用,git实操,git命令和常用指令)

简介:Git是一款代码版本管理工具,可以记录每次提交的代码,防止代码丢失,可实现版本迭代,解决代码冲突,常用的远程Git仓库:Gitee(国内)、GitHub(国外&#xff…

接口请求的六种常见方式详解(get、post、head等)

一.接口请求的六种常见方式: 1、Get 向特定资源发出请求(请求指定页面信息,并返回实体主体) 2、Post 向指定资源提交数据进行处理请求(提交表单、上传文件),又可能导致新的资源的建…

封装console

目的 1. 封装console.log , 使得打印更美观方便 2. 同时希望上线后不在打印消耗资源 例图: export const prettyLog () > {const isProduction import.meta.REACT_APP_ENV "prod";const isEmpty (value) > {return value null || val…

Flutter 实现dispose探测控件

文章目录 前言一、什么是dispose探测控件?1、通常情况2、使用dispose探测控件 二、如何实现1、继承StatefulWidget2、定义dipose回调3、定义child4、重载Dispose方法5、build child 三、完整代码四、使用示例1、基本用法2、设置定义数据 总结 前言 开发flutter一般…

Java 期末复习 习题集

💖 单选题 💖 填空题 💖 判断题 💖 程序阅读题 1. 读代码写结果 class A {int m 5;void zengA(int x){m m x;}int jianA(int y){return m - y;} }class B extends A {int m 3;int jianA(int z){return super.jianA(z) m;} …

Chapter 6 Frequency Response of Amplifiers

Chapter 6 Frequency Response of Amplifiers 这一节我们学习单极和差分运放的频率响应. 6.1 General Considerations 我们关心magnitude vs 频率, 因此有低通, 带通, 高通滤波器 6.1.1 Miller Effect Miller’s Theorem 考虑impedance Z1和Z2, X和Y之间增益为Av. Z1 Z/(…

spring 启动顺序

BeanFactoryAware 可在Bean 中获取 BeanFactory 实例 ApplicationContextAware 可在Bean 中获取 ApplicationContext 实例 BeanNameAware 可以在Bean中得到它在IOC容器中的Bean的实例的名字。 ApplicationListener 可监听 ContextRefreshedEvent等。 CommandLineRunner 整…

数据结构与算法笔记:基础篇 - 二叉树基础(下):有了如此高效的散列表,为什么还需要二叉树?

概述 上篇文章,我们学习了树、二叉树及二叉树的遍历,本章来学习一种特殊的二叉树,二叉查找树。二叉查找树最大的特点就是,支持动态数据集合的快速插入、删除、查找操作。 之前说过,散列表也是支持这些操作的&#xf…

盘点2024年5月Sui生态发展,了解Sui近期成长历程!

2024年5月是Sui的第一个生日月,Sui迎来了它的上线一周年纪念日。在过去的一年中Sui在技术进步与创新、生态系统的扩展、社区发展与合作伙伴关系以及重大项目和应用推出方面取得重要进展,展示了其作为下一代区块链平台的潜力。 以下是Sui的近期成长历程集…

QT 信号和槽 通过自定义信号和槽沟通 如何自定义槽和信号的业务,让它们自动关联 自定义信号功能

通过信号和槽机制通信,通信的源头和接收端之间是松耦合的: 源头只需要顾自己发信号就行,不用管谁会接收信号;接收端只需要关联自己感兴趣的信号,其他的信号都不管;只要源头发了信号,关联该信号…

STM32 | 独立看门狗 | RTC(实时时钟)

01、独立看门狗概述 在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞,而陷入死循环,程序的正常运行被打断,由单片机控制的系统无法继续工作,会造成整个系统的陷入停滞状态,发生不可预料的后果,所以出于对单片机运行状…

QQ号码采集器-QQ邮箱采集器

寅甲QQ邮箱采集器或QQ号码采集软件, 一款采集QQ号、QQ邮件地址,采集QQ群成员、QQ好友的软件。可以按关键词采集,如可以按地区、年龄、血型、生日、职业等采集。采集速度非常快且操作很简单。

BoardLight - hackthebox

简介 靶机名称:BoardLight 难度:简单 靶场地址:https://app.hackthebox.com/machines/603 本地环境 靶机IP :10.10.11.11 ubuntu渗透机IP(ubuntu 22.04):10.10.16.17 windows渗透机IP(windows11&…

从欧盟弹性法案看软件物料清单(SBOM)

随着网络安全意识的提升和相关法规的推动,SBOM在国际上网络安全实践中的重要性日益凸显。 例如:美国国土安全部(DHS)的 “软件供应链评估工具包”(SCAT)就鼓励软件供应商提供SBOM,以帮助买方评…

重新认识Word —— 制作简历

重新认识Word —— 制作简历 PPT的图形减除功能word中的设置调整页边距进行排版表格使用 我们之前把word长排版文本梳理了一遍,其实word还有另外的功能,比如说——制作简历。 在这之前,我们先讲一个小技巧: PPT的图形减除功能 …

【数据结构】栈和队列-->理解和实现(赋源码)

Toc 欢迎光临我的Blog,喜欢就点歌关注吧♥ 前面介绍了顺序表、单链表、双向循环链表,基本上已经结束了链表的讲解,今天谈一下栈、队列。可以简单的说是前面学习的一特殊化实现,但是总体是相似的。 前言 栈是一种特殊的线性表&…