当前位置: 首页 > news >正文

【C语言加油站】C语言文件操作详解:从“流”的概念到文件的打开与关闭​

文件操作

  • 导读
  • 一、流与标准流
    • 1.1 流
    • 1.2 标准流
  • 二、文件指针
  • 三、文件的打开与关闭
    • 3.1 `fopen()`
    • 3.2 `fclose()`
    • 3.3 函数的使用
  • 结语

封面

导读

大家好,很高兴又和大家见面啦!

在之前的文章中,我们已经对“文件”有了比较全面的认识:

  • 文件是存储在计算机上的信息集合,是程序与数据持久化的重要载体

我们了解了文件的基本操作,如打开、读取、写入和关闭,也区分了文本文件与二进制文件的本质不同:

  • 文本文件以字符编码(如ASCII)方式存储,便于人类直接阅读
  • 二进制文件则保留数据的原始格式,更适合机器高效处理

理解了“什么是文件”以及“文件如何存储”之后,我们自然会问:在C语言中,如何具体实现文件的操作

这就涉及到一个核心概念——“流”(Stream),以及与之相关的文件指针和标准流机制。通过“流”,C语言将不同的输入输出设备(如键盘、屏幕、磁盘文件)抽象为统一的数据通道,使得文件操作变得灵活而一致。

现在,就让我们一起深入探讨C语言中的“流”与文件操作的具体实现。

一、流与标准流

1.1 流

是一个内涵非常丰富的概念,它既指液体或气体这类物质的移动,也是计算机科学中用于抽象描述数据序列或传输过程的重要模型

在物理世界中,“流”最直观的理解就是​​液体或气体的移动​​。例如,河水的流动、空气的流动(风)都是一种流。流体力学就是研究流体运动规律的科学。其核心原理包括:

  • ​​连续性​​:流体被视为连续介质,其物理量在空间中连续变化。
  • 能量守恒​​:以伯努利方程为例,它描述了在不可压缩流体的稳定流动中,速度、压强和高度之间的关系:动能、压力势能和位能之和在流线上保持不变。

在计算机科学中,​​流Stream)​​ 是一个非常重要且基础的抽象概念,它核心是​​数据处理的一种方式​​。它主要用来处理​​一系列有序的数据元素

如何理解这个抽象概念呢?

在成长的过程中,我相信大家都有听过一句话——我们遨游在知识的海洋中

在这句话中,我们就把所学习的各种知识给具象化成了组成海洋的海水,由这些海水汇聚而形成的海洋,我们就将其称之为知识的海洋。

同样的,在计算机邻域中,我们把计算机中的各种数据具象化成河水,这些河水会汇聚成一条河流,不断地在计算机世界中进行流动。

我们可以向这条河流中倒入新的河水(数据),同样的我们也可以从这条河流中取出我们需要的河水(数据)。

但是有一点需要注意:我们不管是倒入新的河水,还是取出我们需要的河水,我们首先需要做的就是找到这条河流,即,我们在进行输入数据和输出数据前,需要先打开流

1.2 标准流

那为什么我们从键盘输⼊数据,向屏幕上输出数据,并没有打开流呢?

那是因为C语⾔程序在启动的时候,默认打开了3个流:

  • stdin标准输⼊流:在⼤多数的环境中从键盘输⼊,scanf函数就是从标准输⼊流中读取数据。
  • stdout标准输出流:⼤多数的环境中输出⾄显示器界⾯,printf函数就是将信息输出到标准输出流中
  • stderr标准错误流:⼤多数环境中输出到显示器界⾯。

这是默认打开了这三个流,我们使⽤scanfprintf等函数就可以直接进⾏输⼊输出操作的。

stdinstdoutstderr三个流的类型是: FILE* ,通常称为文件指针

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

二、文件指针

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

每个被使⽤的文件都在内存中开辟了⼀个相应的文件信息区,⽤来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在⼀个结构体变量中的。该结构体类型是由系统声明的,取名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;

不同的C编译器的 FILE 类型包含的内容不完全相同,但是大同小异。

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

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

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

	FILE* pf = NULL;	// 创建文件指针变量// pf——point file:指向文件的指针

这里我们定义了一个指向 FILE 类型数据的指针变量 pf

pf

可以使 pf 指向某个文件的文件信息区(⼀个结构体变量)。

pf
文件信息区

通过该⽂件信息区中的信息就能够访问该⽂件。

pf
文件信息区
文件

也就是说,通过文件指针变量能够间接找到与它关联的⽂件。

三、文件的打开与关闭

在前面的内容中我们就有介绍过,我们可以对文件执行的基本操作有:创建、销毁、读取、写入……

  • 在我们完成了对文件的创建后,如果我们想要对该文件进行内容的读取和写入操作,那我们首先需要做的就是打开该文件;

  • 当我们在使用完文件,甚至想要销毁文件时,我们则需要先关闭该文件

因此我们首先需要学习的基本操作就是文件的打开与关闭。

在C语言的 stdio.h 这个头文件中,有一系列专门用来进行文件操作的库函数:

  • fclose()——用于关闭一个已经打开的流(文件)
  • fflush()——用于强制将输出流或更新(最近操作为输出)缓冲区中的数据立即写入文件
  • fopen()——用于使用指定模式打开一个文件,并关联一个流
  • freopen()——用于将已有的流重新关联到另一个文件
  • setbuf()——用于为指定的流设置自定义缓冲区或禁用缓冲
  • setvbuf()——用于为指定的流设置缓冲模式(全缓冲、行缓冲、无缓冲)和缓冲区

下面我们主要介绍两个函数——fopenfclose

3.1 fopen()

在 cplusplus.com 网站中有对该函数的详细介绍,有兴趣的朋友可以点击链接进行访问。这里我们对该函数进行一下使用说明:

fopen
从上述的函数说明中我们可看到函数的一个大致用法:

  • 向函数中传入两个参数:要操作的文件名以及对文件的操作模式

那么该函数能够对文件进行哪些具体的操作呢?

mode

简单来说,核心操作有3类:

  • 读文件:对指定的存在文件进行读操作,若文件不存在则会返回错误信息
  • 写文件:对指定文件进行写操作,若文件不存在,则会创建一个新文件
  • 添加数据:对指定文件的末尾追加数据,若文件不存在,则会创建一个新文件

在这三类核心操作中,我们可以细分为以下操作:

  • 读文件:对指定的存在文件进行读操作,若文件不存在则会返回错误信息
    • r :只读操作。为了输入数据,打开一个已经存在的文本文件
    • rb:只读操作。为了输入数据,打开一个二进制文件
    • r+:读写操作。为了读和写,打开一个文本文件
    • rb+:读写操作。为了读和写,打开一个二进制文件
  • 写文件:对指定文件进行写操作,若文件不存在,则会创建一个新文件
    • w:只写操作。为了输出数据,打开一个文本文件
    • wb:只写操作。为了输出数据,打开一个二进制文件
    • w+:读写操作。为了读和写,建立一个新的文件
    • wb+:读写操作。为了读和写,建立一个新的二进制文件
  • 添加数据:对指定文件的末尾追加数据,若文件不存在,则会创建一个新文件
    • a:追加操作。向文本文件末尾添加数据
    • ab:追加操作。向二进制文件末尾添加数据
    • a+:读写操作。在文件末尾进行读写
    • ab+:读写操作。在二进制文件末尾进行读写

fopen 这个函数对给定的操作是否成功,会有相应返回值:

  • 文件打开成功:返回一个指向文件的指针
  • 文件打开失败:返回一个空指针。在大多数的库实现中,如果失败了,也会把 errno 变量设置为系统特定的错误代码

3.2 fclose()

fclose
该函数的用法比较简单:

  • 向函数中传入一个需要关闭的流

如果关闭成功,函数会返回 0 ,如果关闭失败,函数会返回 EOF。并且即使函数关闭失败,作为参数的 FILE* 指针指向的文件所关联的流也会与该文件和缓冲区断开关联。

3.3 函数的使用

了解了这两个函数的基本用法,下面我们就可以来尝试着使用一下这两个函数了:

void test1() {FILE* pf = NULL;	// 创建文件指针变量// pf——point file:指向文件的指针// 这里我采用w+模式来创建一个名为:text.txt的文本文件,并进行读写pf = fopen("text.txt", "w+");// 当文件打开成功if (pf) {// 通过文件输入函数,向文件中写入:"fopen test"fputs("fopen test", pf);// 完成写入操作后,关闭流fclose(pf);}
}

下面我们就来测试一下:

函数使用
此时程序并没有报错,那就说明我们成功创建了这个文件,并对其进行了写操作。由于我们并未对该文件的创建指定路径,因此文件会自动创建在与程序相同的文件夹下:

函数的使用2

可以看到此时我们已经成功创建了这个文件,并且文件名为我们指定的命名。当我们打开该 .txt 文件后,我们就可以查看是否写入成功:

函数的使用3
可以看到,文件中已经写入了我们需要写入的内容。

那我们如何指定文件的路径呢?

很简单,我们只需要在文件名的前面加上其所在路径即可:

函数使用4
从测试结果中我们可以看到,我们最开始通过仅读模式在指定路径中打开该文件时,由于不存在这个文件,因此返回空指针;

perror 的报错中我们也能获取相关信息,之后我们再一次通过仅写模式,成功在指定路径下创建了该文件,并将指定内容写入了文件内。

结语

今天的内容到这里就全部结束了。至此,我们已经对C语言文件操作的核心基础进行了一次深入的探索。让我们一同回顾本次旅程的要点:

  • 核心概念“流”:我们理解了“流”(Stream)作为数据通道的强大抽象,它将多样的输入/输出设备统一起来,使得文件操作变得清晰而一致。

  • 默认的“标准流”:我们认识了程序启动时自动打开的三个标准流——stdin(标准输入)、stdout(标准输出)和 stderr(标准错误),这正是 scanfprintf 等函数能直接工作的原因。

  • 关键钥匙“文件指针”:我们掌握了 FILE* 这个关键数据类型,它是指向文件信息区的指针,是所有文件操作的基础。

  • 文件操作的基本功“打开与关闭”:我们重点学习了 fopenfclose 这一对必须成对使用的函数,详细了解了各种文件打开模式(如 r, w, a, r+ 等)的区别与适用场景,并成功进行了实践。

掌握文件的打开与关闭,只是迈入了文件处理世界的第一步。接下来,我们将学习如何具体地对文件进行读取和写入,探索更多强大的文件操作函数。

如果这篇博客帮助您理清了“流”与文件操作的基本概念,请不要忘记:

  • 点赞 👍 - 您的认可是我持续创作的最大动力!

  • 收藏 ⭐ - 方便日后随时查阅,巩固知识。

  • 转发 ➤ - 分享给更多可能正在学习C语言的朋友,大家一起进步!

  • 评论 💬 - 您有任何疑问、想法或指正,都欢迎在评论区留言,我们一起交流探讨!

期待在下一篇关于文件读写的博客中与您再次相遇!

http://www.dtcms.com/a/470875.html

相关文章:

  • 涪陵网站建设公司国内可以上的网站
  • 国产CAD皇冠CAD(CrownCAD)三维建模教程:变压器
  • 网站博客程序logo智能设计一键生成器
  • 网站空间可以通过什么获取专业做鞋子的网站有哪些
  • 优秀企业网站设计欣赏电商网站建设意义
  • PwnKit提权漏洞复现:原理分析+环境搭建+渗透实践(CVE-2021-4034)
  • 李宏毅机器学习笔记19
  • 腾讯建设网站视频下载深圳坪山天气
  • 群晖wordpress主机兰州seo新站优化招商
  • Go语言实现HTML转PDF
  • 深入解析Java NIO:从BIO到Reactor模式的网络编程演进
  • 公司怎么做网站推广北京西站停车场收费标准
  • 企业网站系统手机版住房与城乡建设部建设环境工程技术中心网站
  • 非法期货做网站安康信息平台
  • MySQL安装包下载成功,如何跨版本备份迁移无忧?
  • ASM架构基础与核心概念
  • 每天五分钟深度学习:正则化技术解决过拟合(高方差)问题
  • 局域网建设个人网站美食网站设计论文
  • 使用 systemd 管理 MySQL 服务
  • 做网站客户最关心哪些问题下载百度电商平台app
  • 消防电器具工程量-图形识别快速计算
  • 印度股票市场数据接口,支持实时行情、IPO新股、公司信息、技术分析等多种功能
  • 顺德 网站开发 招聘工程平台网
  • 网站建设开发网站案例项目费用插画原画十大培训机构
  • 排查素材下载过慢或失败问题
  • 小网站托管费用大连网站建设 仟亿
  • 基于单片机的窗帘、灯光、空调智能家居控制系统设计
  • Docker存储体系深度解析
  • 如何基于OneAPI构建langchain RAG系统
  • 网站建设说明书模板wordpress菜单结构