【C语言】23.文件操作

由于要对数据进行持久化保存,我们就有了文件。

一、程序文件与数据文件

磁盘(硬盘)上的文件是文件。
但是在程序设计中,我们⼀般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)。

1.1 程序文件

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

1.2 数据文件

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

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

1.3 文件名

⼀个文件要有⼀个唯⼀的文件标识,以便用户识别和引用。
文件名包含3部分:文件路径+文件名主干+文件后缀
例如: c:\code\test.txt
分为绝对路径和相对路径,为了方便起见,文件标识常被称为文件名。

二、二进制文件与文本文件

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

⼀个数据在文件中是怎么存储的呢?
字符⼀律以ASCII形式存储,数值型数据既可以用ASCII形式存储,也可以使用二进制形式存储。
如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符⼀个字节),而二进制形式输出,则在磁盘上只占4个字节。
在这里插入图片描述

三、文件的打开与关闭

3.1 流与标准流

3.1.1流

我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输入输出操作各不相同,为了方便程序员对各种设备进行方便的操作,我们抽象出了流的概念,我们可以把流想象成流淌着字符的河。
C程序针对文件、画面、键盘等的数据输入输出操作都是通过流操作的。
⼀般情况下,我们要想向流里写数据,或者从流中读取数据,都是要打开流,然后操作。

3.1.2 标准流

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

那是因为C语言程序在启动的时候,默认打开了3个流:
• stdin - 标准输入流,在大多数的环境中从键盘输入,scanf函数就是从标准输入流中读取数据。
• stdout - 标准输出流,大多数的环境中输出至显示器界面,printf函数就是将信息输出到标准输出流中。
• stderr - 标准错误流,大多数环境中输出到显示器界面。

这是默认打开了这三个流,我们使用scanf、printf等函数就可以直接进行输入输出操作的。
stdin、stdout、stderr 三个流的类型是: FILE* ,通常称为文件指针。
C语言中,就是通过 FILE* 的文件指针来维护流的各种操作的。

3.2 文件指针

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

定义pf是⼀个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是⼀个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够间接找到与它关联的文件
在这里插入图片描述

3.3 文件的打开与关闭

文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。
在编写程序的时候,在打开文件的同时,都会返回⼀个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。
ANSI C 规定使用 fopen 函数来打开文件, fclose 来关闭文件。
在这里插入图片描述
在这里插入图片描述
mode表示文件的打开模式,下⾯都是文件的打开模式:

文件使用方式含义如果指定文件不存在
r(只读)为了输入数据,打开⼀个已经存在的文本文件出错
w(只写)为了输出数据,打开⼀个文本文件建立一个新的文件
a(追加)向文本文件尾添加数据建立一个新的文件
rb(只读)为了输入数据,打开⼀个二进制文件出错
wb(只写)为了输出数据,打开⼀个二进制文件建立⼀个新的⽂件
ab(追加)向⼀个⼆进制文件尾添加数据建立⼀个新的文件
r+(读写)为了读和写,打开⼀个文本文件出错
w+(读写)为了读和写,建立⼀个新的文件建立⼀个新的文件
a+(读写)打开⼀个⽂件,在文件尾进行读写建立⼀个新的文件
rb+(读写)为了读和写打开⼀个⼆进制文件出错
wb+(读写)为了读和写,新建⼀个新的⼆进制⽂件建立⼀个新的文件
ab+(读写)打开⼀个⼆进制文件,在文件尾进行读和写建立⼀个新的⽂件

四、文件的顺序读写

4.1 顺序读写函数介绍

函数名功能适用于
fgetc字符输⼊函数所有输入流
fputc字符输出函数所有输出流
fgets文本行输入函数所有输⼊流
fputs文本行输出函数所有输出流
fscanf格式化输入函数所有输⼊流
fprintf格式化输出函数所有输出流
fread⼆进制输⼊⽂件
fwrite⼆进制输出⽂件

上面的适用于所有输入流⼀般指适用于标准输入流和其他输入流(如文件输入流);所有输出流⼀般指适用于标准输出流和其他输出流(如文件输出流)

4.2 函数对比

函数功能
scanf针对标准输入(键盘)的格式化输入函数
printf针对标准输出(屏幕)的格式化输出函数
fscanf针对所有输入流的格式化输入函数
fprintf针对所有输出流的格式化输出函数
sscanf从一个字符串中读取一个格式化的数据
sprintf把一个格式化的数据转换为字符串

五、文件的随机读写

5.1 fseek

根据文件指针的位置和偏移量来定位文件指针。
在这里插入图片描述
在这里插入图片描述

5.2 ftell

返回文件指针相对于起始位置的偏移量
在这里插入图片描述

5.3 rewind

让文件指针的位置回到文件的起始位置
在这里插入图片描述

六、文件结束的判断

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

6.1 feof

在文件读取结束后,判断是否是因为遇到文件末尾而结束。
在这里插入图片描述

6.2 ferror

在文件读取结束后,判断是否是因为遇到错误而结束。
在这里插入图片描述

6.3使用的例子

6.3.1文本文件

#include <stdio.h>
#include <stdlib.h>int main(void)
{int c; // 注意:int,⾮char,要求处理EOF FILE* fp = fopen("test.txt", "r");if(!fp) {perror("File opening failed");return EXIT_FAILURE;}//fgetc 当读取失败的时候或者遇到⽂件结束的时候,都会返回EOF while ((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);return 0;
}

6.3.2二进制文件

#include <stdio.h>enum { SIZE = 5 };
int main(void)
{double a[SIZE] = {1.,2.,3.,4.,5.};FILE *fp = fopen("test.bin", "wb"); // 必须⽤⼆进制模式 fwrite(a, sizeof *a, SIZE, fp); // 写 double 的数组 fclose(fp);double b[SIZE];fp = fopen("test.bin","rb");size_t ret_code = fread(b, sizeof *b, SIZE, fp); // 读 double 的数组 if(ret_code == SIZE) {puts("Array read successfully, contents: ");for(int n = 0; n < SIZE; ++n) printf("%f ", b[n]);putchar('\n');} else { // error handlingif (feof(fp))printf("Error reading test.bin: unexpected end of file\n");else if (ferror(fp)) perror("Error reading test.bin");} fclose(fp);
}

七、文件缓冲区

ANSIC 标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每⼀个正在使用的文件开辟⼀块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才⼀起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。
在这里插入图片描述
因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。
如果不做,可能导致读写文件的问题。

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

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

相关文章

“论云上自动化运维及其应用”写作框架,软考高级论文,系统架构设计师论文

论文真题 云上自动化运维是传统IT运维和DevOps的延伸&#xff0c;通过云原生架构实现运维的再进化。云上自动化运维可以有效帮助企业降低IT运维成本&#xff0c;提升系统的灵活度&#xff0c;以及系统的交付速度&#xff0c;增强系统的可靠性&#xff0c;构建更加安全、可信、…

2024年最适合Python小白的零基础入门教程!

伴随着云计算、大数据、AI等技术的迅速崛起&#xff0c;市场对Python人才的需求和市场人才的匮乏&#xff0c;让长期沉默的Python语言一下子备受众人的关注&#xff0c;再加上简单易学&#xff0c;使得Python一跃成为TIOBE排行榜的第一。 准备学Python或者想学Python的小伙伴们…

13 Redis-- 数据一致性模型、MySQL 和 Redis 的数据一致性

数据一致性模型 根据一致性的强弱分类&#xff0c;可以将一致性模型按以下顺序排列&#xff1a; 强一致性 > 最终一致性 > 弱一致性 数据一致性模型一般用于分布式系统中&#xff0c;目的是定义多个节点间的同步规范。 在这里&#xff0c;我们将其引入数据库和缓存组…

【正点原子K210连载】第十四章 按键输入实验 摘自【正点原子】DNK210使用指南-CanMV版指南

1&#xff09;实验平台&#xff1a;正点原子ATK-DNK210开发板 2&#xff09;平台购买地址https://detail.tmall.com/item.htm?id731866264428 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/docs/boards/xiaoxitongban 第十四章 按键输入实…

Vue3 登录成功,浏览器存在toke,再次访问/login路由到/index 首页页面

文章目录 目录 文章目录 流程 小结 概要流程技术细节小结 概要 首先需要清楚知道浏览器localstorage和Session storage的区别 localStorage 和 sessionStorage 是 HTML5 提供的两种客户端存储数据的方法&#xff0c;它们在使用和生命周期上有一些区别&#xff1a; 1. 生命周期…

@Cacheable解决复杂对象形参导致的缓存失效问题(如Map参数)

在Spring中使用 Cacheable 注解可以非常方便地实现方法的自动缓存机制。如以下代码&#xff1a; Cacheable(value "YwtbToken", key "#p0") public String createToken(String dlzh) {...}但当Cacheable 注解修饰的方法参数使用了复杂对象&#xff0c;如…

物联网数据可视化利器:云组态设计器全新升级

数据可视化已成为数据展示与分析领域非常重要的工具。由多种图表、3D图形组成的大屏能够帮助用户非常直观简洁地了解数据。在物联网环境下,用户在制作数据展示大屏时,对数据可视化工具提出了更高的要求,例如能够展示3D组件、灵活的图层结构、支持多种数据源、实时的数据更新、图…

函数创建单链表---无n型,需要 while 循环 + scanf

题目&#xff1a; #include <stdlib.h> struct link{int data;struct link *next; }; struct link* creatLink(); int main(){struct link *head,*p;headcreatLink();for(phead->next ;p;pp->next )printf("%d ",p->data );return 0; }/* 请在这里填…

软考《信息系统运行管理员》-2.1信息系统运维的管理

2.1信息系统运维的管理 信息系统运维管理体系框架 信息系统运维管理主要流程的目标 标准化&#xff1a;通过流程框架&#xff0c;构件标准的运维流程流程化&#xff1a;将大部分运维工作流程化&#xff0c;确保工作可重复&#xff0c;并且这些工作都有质量的完成&#xff0c;…

线性代数|机器学习-P20鞍点和极值

文章目录 1 . 瑞利商的思考1.1 瑞利商的定义1.2 投影向量 2. 拉格朗日乘子法3. 鞍点4. 线性拟合4.1 范德蒙矩阵线性拟合4.2 python 代码4.3 范德蒙矩阵缺点 5. 均值和方差5.1 样本均值和方差5.2 总体期望 μ \mu μ,总体方差 σ 2 \sigma^2 σ2 1 . 瑞利商的思考 1.1 瑞利商…

MySQL学习(6):SQL语句之数据控制语言:DCL

DCL用来管理数据库用户&#xff0c;控制数据库的访问权限 1.管理用户 1.1查询用户 use mysql; select * from user; #用户信息都存放在系统数据库mysql的user表中 在user表中&#xff0c;一个用户是由用户名和主机名共同决定的&#xff0c;上图中的host一栏就是用户的主机名…

常用组件详解(二):torchsummary

文章目录 一、基本使用二、常见指标2.1Input size2.2Forward/backward pass size 一、基本使用 torchsummary库是一个好用的模型可视化工具&#xff0c;用于帮助开发者把握每个网络层级的细节&#xff0c;包括其中的连接和维度。使用方法&#xff1a; from torchsummary impor…

ubuntu 安装docker

目录 docker 打包与加载 加载 Docker 镜像&#xff1a; ubuntu 安装docker 系统版本 检查卸载老版本docker 安装步骤 运行docker docker 打包与加载 打包成 .tar 文件&#xff1a; tar -cvf my-docker-image.tar * 加载 Docker 镜像&#xff1a; docker load -i my-d…

Access Levels in Swift

Access Levels (访问级别) Swift provides six different access levels for entities(实体) within your code. These access levels are relative to the source file in which an entity is defined, the module(模块) that source file belongs to, and the package that …

分享一个超级实用的东西——巴比达远程访问

前言 &#x1f388;家人们&#xff0c;今天我要和你们分享一个超级实用的东西——巴比达远程访问&#xff01;&#x1f389; &#x1f4bb;有了它&#xff0c;无论你身在何处&#xff0c;都能轻松访问家中的电脑&#x1f4bb;&#xff0c;就像在身边一样方便&#xff01;&…

短视频电商源码如何选择

在数字时代的浪潮下&#xff0c;短视频电商以其直观、生动、互动性强的特点&#xff0c;迅速崛起成为电商行业的一股新势力。对于有志于进军短视频电商领域的创业者来说&#xff0c;选择一款合适的短视频电商源码至关重要。本文将从多个角度探讨如何选择短视频电商源码&#xf…

携程礼品卡能转出去吗?

携程的卡好像只能在旅游的时候用 像买车票啊&#xff0c;机票啊&#xff0c;酒店&#xff0c;景点门票啥的&#xff0c;但是如果我没有出游计划的话 这个卡是不是就要被闲置下来&#xff1f; 这个问题一直让我感到很苦恼&#xff0c;还好有收卡云&#xff0c;不然我的携程卡…

模型部署:C++libtorch实现全连接模型10分类和卷积模型ResNet18的四分类的模型部署推理

Clibtorch实现模型部署推理 模型 全连接模型&#xff1a;公开mnist手写识别数字的十分类卷积模型&#xff1a;自行采集的鲜花四分类 部署 语言环境&#xff1a;C 对比Python python是解释性语言&#xff0c;效率很慢&#xff0c;安全性很低 系统开发一般是java、C/C&…

在 CentOS 上安装 Docker Engine

前言 Docker 是啥之类的就不必多说了&#xff0c;直接上安装步骤。 官网安装教程地址&#xff1a;https://docs.docker.com/engine/install/centos/ 1.Uninstall old versions &#xff08;卸载旧版本&#xff09; Older versions of Docker went by docker or docker-engin…

NLP特征提取的惊人历史演变

NLP特征提取的惊人演变 1.理解特征提取2. 文本表示的演变2.1.词袋的简单性2.2. N-Gram 模型的进步2.3. TF-IDF 的崛起 3. 深入研究词嵌入3.1.探索 Word2Vec3.2.深入了解 GloVe3.3.深入研究 FastText 4. 上下文嵌入的影响4.1 ELMo 的突破4.2 理解 BERT 的机制4.3 Transformer的出…