【C语言】文件操作(终卷)

前言

我们在上一卷中了解了顺序读写的函数,现在就让我们从随机读写的函数开始吧。

什么是随机读写?

就是想在哪个位置读或写都行,比较自由。文件打开时光标默认在起始位置。想从后面的某个部分读或写,就得让文件指针来到那个位置:

fseek函数

这个函数就能根据文件指针的位置和偏移量来定位文件指针(文件内容的光标,不是指FILE*类型的文件指针)。

 这个函数有3个参数,第一个是文件指针,第二个是偏移量,第三个指的是起始位置。毕竟,要给出从哪开始,偏移量是多少,才能随机读写。

 注意,offsetof可以为负数

最后一个参数origin有三种选项

第一个是文件的起始位置;第二个是文件指针(光标)当前的位置;第三个是文件的末尾。

请看下面的代码: 

 可以看到我们用fgetc两次读文件时,第一次结果是a,第二次是b,这说明什么?说明第二次读的时候我们的光标向后一移了一个字符。

 光标是一个个移动的,如果我们现在想直接读到e,就不能使用这种方式。

使用fseek定位到起始位置偏移量为4的位置也就是指向e的位置,再读,就得到了e。

 或者我们最后一个参数使用SEEK_END:

或者SEEK_CUR:

 

ftell函数

返回文件指针相较于起始位置的偏移量:

当我们读文件不知道读到哪了,偏移量是多少,就可以使用它。

我们分析一下偏移量为5:

 e读完后其实光标会移动到e的后一位也就是指向f。所以读完e算偏移量,就是5。

rewind函数

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

我们使用完再读就是a:

文件结束的判定

被误解的函数 feof

EOF——end of file 文件结束标志

所以很多人以为feof是用来判断文件是否结束的。

实际上,它的作用是当文件读取结束的时候,判断读取结束的原因是否是遇到文件结尾。

在读取文件的过程中可能读取结束,结束的原因可能是确实遇到了文件末尾(读完了),也可能遇到了错误。那么为了判断,我们就可以使用feof。

feof负责判断是否是因为遇到文件末尾而结束的。而不是判断是否读取结束。

那么怎么判断是否读取结束呢?对于文本文件而言,用fgetc正常读到字符返回的是读到字符的ASCII码值,失败或读取结束会返回EOF;用fgets判断的话(一行一行读),读取失败或者读取结束返回NULL。 所以用fgetc去读判断是否为EOF,用fgets去读判断返回值是否为NULL,就能知道是否读取结束; 

而如果是以二进制的形式去读,返回值小于实际要读的个数就是读取结束的标志。(讲fread时提到过:参数count是一次读几个,如果返回值比num小,说明读取结束)

文本文件判定读取结束原因例子:

二进制文件判定读取结束原因的例子:

注意:没有读到文件结尾时,没有任何状态值被设置,feof的返回值会是0;如果读到文件末尾,返回非零值(一般为1)。

那ferror呢?没有错误时返回0,有错误时返回非零值(1)。那么什么时候会错呢?比如要写文件却以"r"打开文件,要读文件却以"w"形式打开,就会ferror返回1(但是这种情况perror打印不了正确的错误信息,可以自己编写一个错误信息)

 可以看到返回值部分的描述和feof是非常相似的。

文件缓冲区

程序数据区和硬盘之间的输入、输出并不是直接进行的,而是在中间还有一个文件缓冲区:

ANSIC标准采用“缓冲文件系统”处理数据⽂件,所谓缓冲文件系统是指系统自动地在内存中为程序中每⼀个正在使用的文件开辟⼀块“文件缓冲区”。

从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才⼀起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小是根据C编译系统决定的。

为什么要有文件缓冲区?

这就像你去找老师提问,一遇到一个问题就跑去问老师,一分钟去一次,老师时间就会被你占用,只能给你一个人解答;但如果你攒够多个问题再一起提问,老师就能腾出时间做别的事。

所以我们也不是有一个数据就写到硬盘上的,写数据不是直接就能写上去的,还要调用操作系统的接口,如果我们一有数据就写,总是打断操作系统;现在有了缓冲区,充满了再写入硬盘,操作系统就能做其他事,提高了效率。

观察缓冲区例子:

注意,第二次Sleep是因为文件关闭时也会刷新缓冲区,为了保证缓冲区的刷新不是因为关闭文件,延缓关闭文件。 

所以我们得出一个结论

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

到此,文件操作的内容就结束了,祝阅读愉快^_^

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】宏详解(上卷)

前言 紧接着预处理详解(上卷),接下来我们来讲宏(隶属于预处理详解系列)。 #define定义宏 #define机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro&#xff…

图解 Python 编程(12) | 文件和编码方式

🌞欢迎来到Python 的世界 🌈博客主页:卿云阁 💌欢迎关注🎉点赞👍收藏⭐️留言📝 🌟本文由卿云阁原创! 📆首发时间:🌹2024年6月9日&am…

使用 Scapy 库编写 TCP 劫持攻击脚本

一、介绍 TCP劫持攻击(TCP Hijacking),也称为会话劫持,是一种攻击方式,攻击者在合法用户与服务器之间的通信过程中插入或劫持数据包,从而控制通信会话。通过TCP劫持,攻击者可以获取敏感信息、执…

(2024,扩散,DMP,提示混合,动态门控,阶段特异性,微调)通过混合提示进行扩散模型修补

Diffusion Model Patching via Mixture-of-Prompts 公和众和号:EDPJ(进 Q 交流群:922230617 或加 VX:CV_EDPJ 进 V 交流群) 目录 0 摘要 1 简介 2 相关工作 3 扩散模型修补(DMP) 3.1 架构…

【召回第一篇】召回方法综述

各个网站上找的各位大神的优秀回答,记录再此。 首先是石塔西大佬的回答:工业界推荐系统中有哪些召回策略? 万变不离其宗:用统一框架理解向量化召回前言常读我的文章的同学会注意到,我一直强调、推崇,不要…

transformer中对于QKV的个人理解

目录 1、向量点乘 2、相似度计算举例 3、QKV分析 4、整体流程 (1) 首先从词向量到Q、K、V (2) 计算Q*(K的转置),并归一化之后进行softmax (3) 使用刚得到的权重矩阵,与V相乘,计算加权求和。 5、多头注意力 上面…

python爬虫入门教程(二):requests库的高级用法

requests库除了基本的GET和POST请求外,requests库还提供了许多高级功能,本文将介绍其中一些常用的用法。包括: 会话保持(Session)SSL证书验证文件上传代理设置自定义HTTP适配器超时设置 请求参数 文章最开始&#x…

dockerhub不可用临时解决方案

近日,在拉取一些docker hub的镜像的时候死活拉不下来,要么超时,要么无法接站点地址,不管是docker hub,还是国内镜像站,统统都不行了。 经过各大媒体报道,以及自己的亲身验证,才知道&#xff0c…

android集成百度文心一言实现对话功能,实战项目讲解,人人都能拥有一款ai应用

大家好,今天给大家讲解下如何实现一个基于百度文心一言的app功能,app内部同时集成了讯飞的语音识别。本文适用于有android基础的小伙伴阅读,文章末尾放上本项目用到的全部实例代码,在使用前请务必看完本文章。 先来给大家看看效果…

Spring的Controller是单例还是多例,如何保证线程安全的。

目录 验证是否单例(默认单例) 多例测试 单例对象成员变量测试 多例对象成员变量测试 解决方案 结论: 补充说明 答案:controller默认是单例的,不要使用非静态的成员变量,否则会发生数据逻辑混乱。 正…

Windows下SVN文件损坏,启动服务报错1067

之前碰到过一次,忘记最后怎么解决的了,只记得大概原理和原因,以及解决办法。 1067错误码,很多地方都会碰到,mysql也会有,看来应该是windows系统的错误码。跟具体程序无关。所以直接百度“SVN”、“1067”…

【Python报错】已解决ValueError: Expected 2D array, got 1D array instead

成功解决“ValueError: Expected 2D array, got 1D array instead”错误的全面指南 一、引言 在Python的数据分析和机器学习领域,尤其是使用NumPy、Pandas、scikit-learn等库时,经常会遇到各种类型错误。其中,“ValueError: Expected 2D arr…

AI菜鸟向前飞 — LangChain系列之十七 - 剖析AgentExecutor

AgentExecutor 顾名思义,Agent执行器,本篇先简单看看LangChain是如何实现的。 先回顾 AI菜鸟向前飞 — LangChain系列之十四 - Agent系列:从现象看机制(上篇) AI菜鸟向前飞 — LangChain系列之十五 - Agent系列&#…

大模型的发展历程

1、早期模型的探索与局限性 1.1早期模型的探索与局限性 从早期的符号逻辑到现代的深度学习 1 模型,AI 领域经历了数十年的探索和迭代,为后续突破打下了坚实基础。随着大数据的发展和 AI 计算能力的爆炸式增长,深度学习模型的崛起显得尤为突出…

有序二叉树java实现

类实现: package 树;import java.util.LinkedList; import java.util.Queue;public class BinaryTree {public TreeNode root;//插入public void insert(int value){//插入成功之后要return结束方法TreeNode node new TreeNode(value);//如果root为空的话插入if(r…

人工智能_机器学习096_PCA主成分分析降维算法_PCA降维原理_介绍和使用_模式识别_EVD特征值分解_SVD奇异值分解---人工智能工作笔记0221

首先我来看PCA降维,可以看到在图像处理中经常用到PCA,经过对数据进行降维可以去除数据噪声,发现数据中的模式,也就是 发现数据的规律. 这里的模式识别就是 机器学习中的一个分支 就是在数据中找规律的意思 我们使用代码看一下 from sklearn.docomposition import PCA from skl…

kivy 百词斩项目 报错

AttributeError: FigureCanvasKivyAgg object has no attribute resize_event AttributeError: FigureCanvasKivyAgg object has no attribute resize_event 是一种常见的Python错误,当你试图访问一个对象(在这个例子中是 FigureCanvasKivyAgg 对象&am…

六、主存储器管理,计算机操作系统教程,第四版,左万利,王英

文章目录 [toc]一、存储管理的功能1.1 存储分配1.2 存储共享1.3 存储保护1.4 存储扩充1.5 地址映射 二、内存资源管理2.1 内存分区2.1.1 静态分区与动态分区2.1.2 等长分区与异长分区 2.2 内存分配2.2.1 静态等长分区的分配2.2.2 *动态异长分区的分配 2.3 碎片与紧凑 三、界地址…

从C到C++,C++入门(2)

在C入门篇(1)中,博主为大家简单介绍了什么是C,以及C中的关键字,命名空间,输入与输出和缺省参数的相关知识。今天就让我们继续一起学习C的基础知识点吧!! 1.函数重载 1.1函数重载的概…

C# WPF入门学习主线篇(十九)—— 布局管理实战『混合布局案例』

C# WPF入门学习主线篇(十九)—— 布局管理实战『混合布局案例』 欢迎来到C# WPF入门学习系列的第十九篇。在前几篇文章中,我们详细介绍了各个布局容器的基本概念和使用方法。本篇博客将通过一个综合的实战案例,展示如何在WPF中使用…