【再识C进阶5(上)】详细介绍C语言文件操作——文件是用于存储数据

news2024/11/17 8:47:38

前言

💓作者简介: 加油,旭杏,目前大二,正在学习C++数据结构等👀
💓作者主页:加油,旭杏的主页👀

⏩本文收录在:再识C进阶的专栏👀

🚚代码仓库:旭日东升 1👀

🌹欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖

学习目标:

       在上一篇博客中,我们学习了一些自定义类型,比如:结构体、枚举和联合。那么这一篇和之前讲的所有内容都不是和相关,因为这涉及到了数据存储的内容

       相信每一个计算机学子都会有一门课设——XX管理系统(通讯录),那么你们有没有出现这么一种情况:首先,你运行程序,在通讯录中写下一些数据,然后关闭程序,当下次打开程序时发现之前所写的数据全都不见了。那么这一节就是讲述了如何将数据存储起来在下一次运行程序时可以找到不丢失。这时就凸显出数据储存的重要性,文件是最简单的一个。


学习内容:

通过上面的学习目标,我们可以列出要学习的内容:

  1. 什么是文件以及为什么使用文件
  2. 文件是如何打开和关闭的
  3. 文件的顺序读写和随机读写
  4. 文本文件和二进制文件
  5. 文件读取结束的判定
  6. 文件的缓冲区

一、为什么使用文件

       我们前面在学习结构体时,写了通讯录的程序,当通讯录运行起来时,可以在通讯录中增加、删除数据,此时数据是存放在内存中,当程序退出时,通讯录中的数据自然就不存在了,等下次运行通讯录程序的时候,数据又要重新输入,如果这样使用通讯录就比较难受。

       我们在想既然是通讯录就应该将信息记录下来,只有我们自己在选择是否删除数据才能删除,数据才不复存在。这样就涉及到了数据持久化的问题,我们一般数据持久化的方法有:1. 利用磁盘,将数据存放在磁盘中2. 利用数据库,将数据存放在数据库中3. 利用文件,将数据存放在文件中

总结:

将数据持久化的方法有:

  1. 利用磁盘将数据存放在磁盘中
  2. 利用数据库将数据存放在数据库中
  3. 利用文件将数据存放在文件中

二、什么是文件

       磁盘中的文件就是文件。但是在程序设计中,我们一般谈到的文件有两种:程序文件数据文件

2.1 程序文件

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

2.2 数据文件(本章重点)

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

       在这章之前,我们所处理数据的输入和输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显示器中。

       在这里有一个终端的名词,其解释为:经由通信设施向计算机输入程序和数据或接收计算机输出处理结果的设备听着可能有点懵,让我们来举一些例子吧!

       外围设备包括显示器鼠标键盘耳机麦克风、和摄像头等等。这些外围设备就被称为终端,负责向主机输入数据的就叫输入终端,比如鼠标、键盘、麦克风、摄像头,负责接收主机输出数据的设备就被称作输出终端,比如显示器、耳机。

       其实有时候我们会将信息输出到磁盘中,当需要的时候,在将其从磁盘上把数据读取到内存中使用,这里处理的是磁盘的文件。

2.3 文件名

       知道了为什么使用文件,以及文件的分类,我们如何使用文件呢?使用这个文件前,我们肯定要知道这个文件的文件名是什么?那么我们接下来来学习文件名。

       文件名就如同我们自己的姓名,只有我们有了这个名字后,我们才知道何人叫我们做何事,因此,文件也一样,一个文件要有一个唯一的文件标识,以便于用户识别和引用,否则会产生异议。文件名包含3个部分:文件路径 + 文件名主干 + 文件后缀(有时也可以不写文件后缀)

举个栗子:

c:\code\test.txt

       为了方便起见,文件标识常被称为文件名

插曲:文件路径 

       在讲述完文件名后,我们给大家在写一个陌生的概念:文件路径文件路径常常被分为两种:绝对路径相对路径

  • 绝对路径就是从这个文件所在跟开始写,比如从D盘开始写;
  • 相对路径就是从这个文件所在的目录相对于工程所在目录有几个等级,. 表示当前路径, .. 表示上一级路径。

注意:

在文件夹中一定要把显示文件扩展名打开,防止文件命名错误,导致多谢一个文件后缀。

三、文件的打开和关闭

3.1 文件指针

3.1.1 文件指针的介绍

       上述学完文件名之后,我们要如何使用文件,是利用什么我们才能打开文件,并且在写完文件后关闭文件?在之前我们学习过程中,我们学习指针的相关概念,知道了如何引用指针找到我们所要使用的变量,那么文件指针也是一样,在缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”

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

例如,在VS2013编译环境中提供的 stdio.h 头文件有以下文件类型的声明:(看看就行)

struct _ioduf{
    char* _ptr;
    int _cnt;
    char* _base;
    int _flag;
    int _file;
    int _charbuf;
    int _bufsiz;
    char* _tmpfname;
};
//类型重定义,将其定义为FILE
typedef struct _iobuf FILE;

       不同的编译器的FILE类型包含的内容是不完全相同的,但是大同小异。每当打开一个文件的时候,系统会根据文件的情况自动建一个FILE结构的变量,并填充其中的信息使用者不必关心实现细节。一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来比较方便。

3.1.2 文件指针的使用

在了解完文件指针是什么,下面我们可以创建一个FILE*的指针变量

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

       定义 pf 是一个指向FILE类型的指针变量,可以使pf指向某个文件的文件信息区(是一个结构体变量)也就是可以通过指针来操纵一个文件,怎么通过指针找到文件信息区是不需要关心的。我们可以通过文件信息区的信息来访问该文件。

总结:通过文件指针变量能够找到与它相关联的文件。

3.2 文件的打开和关闭 

       介绍完文件指针,就要开始使用文件指针了。举个简单的例子:如果小明想要喝饮料,首先,要先打开饮料的瓶盖;然后,进行喝饮料;最后,喝完饮料要将瓶盖拧紧。文件的使用方法和其一模一样,要先将文件打开,最后将文件进行关闭,下面我们来学习如何将文件打开和关闭。

       文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。ANSIC规定使用 fopen 函数来打开文件fclose 函数来关闭文件

//打开文件
FILE* fopen (const char* filename, const char* mode);
//第一个参数是要操作的文件名,第二个参数是打开文件的方式
//关闭文件
int fclose (FILE* stream);

fopen 函数 

       这个函数的返回类型是 FILE*,是一个文件指针;第一个参数是要操作的文件名,第二个参数是打开文件的方式,这两个参数都是字符串,注意写法。

       函数的返回值:如果打开成功,返回打开成功的文件指针;如果打开失败,返回NULL。

fclose 函数 

       这个函数的返回值是整形类型;参数只有一个,是要操作的文件名。这个函数虽然使用 fclose 函数关闭文件,但文件指针依然指向原文件地址处,防止出现野指针,需要将这个文件指针置空。为了验证,看下图:

打开方式如下:

文件使用方式
" r "
" w "
" a "
" rb "
" wb "

实例代码:

四、文件的顺序读写

4.1 什么是流?

       在介绍文件的顺序读写函数之前,我们先来介绍一下什么是,因为下面,我们在介绍函数的时候将讲述这些函数适用于什么流中,下面我们来学习什么是流?

       流是一个高度抽象的概念,我们都知道计算机是用于处理数据的,数据既可以从计算机外部获取,也可以从内部流出,我们来画图分析:

提示:

在C语言程序中,只要运行起来,默认打开3个流: 

在这里,我们先简单了解一下有几个流的分类:

  1. 文件流
  2. 字符流
  3. 标准输入/输出流

4.2 一些读写函数函数

我们先来汇总一下文件中的顺序读写函数:

4.3 对比一组函数

在上方我们学习了那么多的读写函数,我们要进行对比

//三组读写函数的对比
scanf / fscanf / sscanf
printf / fprintf /sprintf

scanf     函数是针对的是标准输入流(键盘)的格式化输入函数

printf     函数是针对的是标准输出流(屏幕)的格式化输出函数

fscanf    函数是针对所有输入流(文件流、标准输入流)的格式化输入函数

fprintf    函数是针对所有输出流(文件流、标准输出流)的格式化输出函数

sscanf   函数是将字符串转化为格式化数据

sprintf   函数是将格式化数据转化为字符串

五、文件的随机读写

       这一部分用的不多,因为如果想要随机读写,是需要将整个文件的信息了解的面面俱到,这样我们才能知道你想要的东西在第几字节处,而且大多数情况下,我们的文件储存的是二进制文件,我们根本就看不懂里面的东西。

5.1 fseek函数

5.2 ftell函数

5.3 rewind函数

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

       在这一小节,我们可以根据数据的组织形式,将数据文件称为文本文件或者二进制文件。为了让大家了解什么是文本文件,什么是二进制文件?看下图:

概念:

二进制文件的概念:

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

文本文件的概念:

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

问题:

一个数据在内存中是怎么存储的?

       字符一律以ASCII码的形式进行存储,数值型数据既可以使用ASCII码的形式进行存储,也可以使用二进制形式进行存储。

举个栗子:

       假如我们有一个整数10000,如果以ASCII码值的形式输出到磁盘中,则磁盘中占用5个字节(每个字符一个字节);而以二进制的形式输出,则在磁盘中占4个字节。

       通过这个例子,我们思考一下,是否用二进制文件更省空间呢?并不是,比如数字1,在文本文件中为一个字节,而在二进制文件中为四个字节。

小编有一点想不明白为什么二进制文件中的信息在记事本中是符号,而不是0或1?

       实际上,由于二进制文件中每一个字符都有256种不同的取值,因此其中的很多值在大多数字符中都没有与之对应的可打印字符,因此,当我们将二进制文件以文本形式打开时,大部分字节都没有对应的可打印字符,就会显示乱码。

七、文件读取结束的判定

7.1 被错误使用的 feof 函数

       虽然这个函数中含有EOF,会使人联想这个函数是用于判断读取文件是否结束,一定要牢牢记住:在文件读取过程中,不能用 feof 函数的返回值直接用来判断文件是否读取结束。这个函数而是用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件末尾结束

7.2 如何判断文件是否读取结束?

       我们可以根据读函数的返回值来判断文件是否读取结束,我们在上面介绍了三个读函数,分别是:fget、fgets、fread。下面我们来讨论一下:

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

  • fgetc判断返回值是否为 EOF
  • fgets判断返回值是否为 NULL

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

  • fread判断返回值是否小于实际要读的个数

7.3 一些例子代码

7.4 文件读取结束后的判断函数

函数:ferror

作用:在文件读取结束后用来判断文件是否因为读取过程中遇到错误而结束的

函数:feof

作用:在文件读取结束后用来判断文件是否因为读取过程中遇到文件结束标志性末尾而结束的

八、文件缓冲区

8.1 文件缓冲区的概念

        ANSIC标准采用“缓冲文件系统”处理的数据文件,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才能一起送到磁盘上。缓冲区的大小由C编译系统决定的。

8.2 为什么使用文件缓冲区

       因为如果不使用文件缓冲区,那么我们每输入一个数据,都让内存去调用一下,这样会浪费大量的时间和经历,所以我们如果将他们打包好,这样就会减少时间。

8.3 结论 

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

学习产出:

  1. 什么是文件以及为什么使用文件
  2. 文件是如何打开和关闭的
  3. 文件的顺序读写和随机读写
  4. 文本文件和二进制文件
  5. 文件读取结束的判定
  6. 文件的缓冲区

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

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

相关文章

成绩查询页面和自助查询方式

科技发展让我们有更多的方式来发布和查询学生成绩。今天,我想向大家介绍什么是成绩查询页面,并分享如何通过各种代码和Excel来实现让学生自助查询成绩。 成绩查询页面是一个专门用来发布和查询学生成绩的网络页面。这个页面具有发布、查询、统计成绩等功…

Vue 3使用 Iconify 作为图标库与图标离线加载的方法、 Icones 开源在线图标浏览库的使用

之前一直naive-ui搭配使用的是xicons,后来发现Iconify支持的图标合集更多,因此转而使用Iconify。 与FontAwesome不同的是,Iconify配合Icones相当于是一个合集,Iconify提供了快捷引入图标的方式,而Icones是一个大的图标…

二、vue基础语法

一、模板语法 1、文本渲染 使用双花括号语法插入文本 <template><div><h3>msg: {{ message }}</h3></div> </template><script> export default {data() {return {message: "输出信息"}} } </script><style s…

SAP 路径及运输功能

一、 概述 SAP的发运功能包括两部份内容&#xff0c;一是运输路径&#xff1b;二是运输功能。运输路径是运输功能的基础。 SAP 中的运输功能是后勤执行的一部分&#xff0c;用于自动计算交货成本&#xff1b;也就是说&#xff0c;SAP 可以让系统自动对销售发货的商品计算运费&…

web APIs——第一天(上)

变量声明的时候建议 const优先&#xff0c;尽量使用const 原因&#xff1a; const语义化更好很多变量我们声明的时候就知道他不会被更改了&#xff0c;那为什么不用const呢&#xff1f;实际开发中也是&#xff0c;比如react框架&#xff0c;基本const如果你有纠结的时候&…

记一次Clickhouse 复制表同步延迟排查

现象 数据从集群中一个节点写入之后&#xff0c;其他两个节点无法及时查询到数据&#xff0c;等了几分钟。因为我们ck集群是读写分离架构&#xff0c;也就是一个节点写数据&#xff0c;其他节点供读取。 排查思路 从业务得知&#xff0c;数据更新时间点为&#xff1a;11:30。…

信驰达RF-BM-2340x系列BLE蓝牙模块正式登录TI官网

信驰达作为TI中国低功耗连接技术第三方IDH&#xff0c;RF-BM-2340x系列低功耗蓝牙模块正式通过TI认证并在全球进行推广。 图 1 TI官网信驰达RF-BM-2340x系列BLE蓝牙模块 一直以来&#xff0c;信驰达重视在无线射频通信领域基础技术上的投入&#xff0c;奠定了公司在低功耗蓝牙…

Redis数据结构之SDS

前言 字符串在 Redis 中的应用场景十分广泛&#xff0c;所有的键都是字符串类型&#xff0c;值也可能是字符串类型。 比如电商系统用 Redis 缓存商品信息&#xff0c;可以把商品 ID 作为键&#xff0c;商品信息序列化为 JSON 后作为值写入&#xff1a; SET item:1001 {"…

使用python自动化操作如何使用subprocess,mac如何查看软件安装路径

使用下面这种方法实现需要配置全局的环境变量&#xff0c;很麻烦 import subprocessdef open_wps_new_doc():try:# 打开WPS应用程序subprocess.Popen(wps)# 等待一段时间&#xff0c;确保WPS完全打开time.sleep(2)# 发送快捷键组合&#xff0c;新建一个Word文档pyautogui.hotk…

linux进阶(3)

课程链接 CH10-2-Apache的其他用途_哔哩哔哩_bilibili scp不够好,因为他需要知道服务器上具体的一个目录

MySQL -- 数据库基础

MySQL – 数据库基础 文章目录 MySQL -- 数据库基础一、基础知识1.什么是数据库2.连接服务器3.服务器、数据库、表的关系3.MySQL架构4.SQL分类5.存储引擎 一、基础知识 1.什么是数据库 文件存储数据有以下几个缺点&#xff1a; 文件的安全性问题文件不利于数据查询和管理文件…

【ARM AMBA5 CHI 入门 12.2 -- CHI 协议层详细介绍 】

文章目录 1 协议层1.1 协议层传输通道1.2 域段1.2.1 ID域段1.2.2 其他关键域段1.2.2.1 Address1.2.2.2 Secure bit1.2.2.3 Memory Attributes1.2.2.4 Transaction attribute combinations 1.4.1 Transaction 路由1.4.2 SAM 介绍1.4.3 Node ID 1.5 节点间数据怎么传输的呢&#…

jdk11的HttpClient

我们都知道在jdk11之前都在用okhttp或者org.apache.httpcomponents 其实早在jdk9的时候这个方案就在孵化中 上面的截图来自openjdk的官网&#xff0c;注&#xff1a;openjdk是个开源项目&#xff0c;不存在侵权现象 这是openjdk的官网&#xff1a;JEP 110: HTTP/2 Client (In…

vue 插槽 作用域插槽

vue 插槽 作用域插槽 **创建 工程&#xff1a; H:\java_work\java_springboot\vue_study ctrl按住不放 右键 悬着 powershell H:\java_work\java_springboot\js_study\Vue2_3入门到实战-配套资料\01-随堂代码素材\day05\准备代码\10-插槽-作用域插槽 vue --version vue crea…

安科瑞关于红外测温技术在变电站运维中的应用

安科瑞 崔丽洁 红外测温技术 特点 工作中的输变电机械设备由于电流热效应产生了红外线照射效应&#xff0c;从而在电气设备表层形成了相应的高温场&#xff0c;而红外线测温高温技术则透过吸取这些自高温场发出的红外线照射热能&#xff0c;并透过电流效应以及放大器和A/D转换器…

Linux - 还不懂 gdb 调试器?(调试软件)

前言 当前&#xff0c;我们可以使用 make/makefile 来程序化执行代码文件&#xff1b;可以使用 gcc/g 等编译器来编译代码&#xff1b;可以使用 vim 编辑器来编写代码&#xff1b;其实在 Linux 当中还有一个工具&#xff0c;可以实现调试工作&#xff0c;这个工具就是 -- gdb。…

RK3568驱动指南|第七期-设备树-第57章 实例分析:中断

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

PHP 基础

PHP 基础 概述 在PHP 文件中&#xff0c;可以与HTML 和JavaScript 混编。 开始标记<?php 表示进入PHP 模式&#xff0c;结束标记?>&#xff0c;标识退出PHP 模式。 PHP 模式之外的内容会被作为字符输出到浏览器中。 PHP 在服务端执行&#xff0c;HTML 和 JS 在浏览…

任何人不知道这款超实用的配音软件,我都会伤心的OK?

看完一段精彩的视频&#xff0c;令人陶醉的原因之一就是配音&#xff0c;有的充满感情&#xff0c;有的字正腔圆&#xff0c;相信很多人都不知道这样的声音是怎么配出来的&#xff1f;今天&#xff0c;小编就来给大家分享一款超实用的配音软件&#xff0c;不仅操作简单&#xf…

STM32:TIM通道输入捕获

本文主要讲解如何使用TIMER通道的输入脉冲捕获功能。基于STM32F7的Timer2 Channel3来进行讲解。 配置时钟 Timer2的时钟频率&#xff0c;对应APB1 Timer。 分频设置为96-1&#xff0c;这样设置每次count计数&#xff0c;对应的时间为1us。Counter设置为最大即可&#xff0c;默…