C文件操作2

五、文件的随机读写

这些函数都需要包含头文件 #include<stdio.h>

5.1 fseek

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

重新定位流位置指示器

int fseek ( FILE * stream, long int offset, int origin );

  • 将与流关联的位置指示器设置到一个新的位置。
  • 对于以二进制模式打开的流,新位置是通过将偏移量(offset)加到由起始点(origin)指定的参考位置来确定的。
  • 对于以文本模式打开的流,偏移量必须为零或者是之前调用 ftell 函数所返回的值,并且起始点必须是 SEEK_SET
  • 如果操作成功,该函数返回零。否则,它返回非零值。
  • 如果发生读或写错误,错误指示器(`ferror`)将被设置。 

fseek函数的起始点(参考点)有三种类型:

int main()
{FILE* pf = fopen("test.txt","r");if(pf == NULL){perror("fopen");}else{int ch = fgetc(pf);printf("%c\n",ch);//ach = fgetc(pf);printf("%c\n",ch);//bch = fgetc(pf);printf("%c\n",ch);//c//如果继续往下读,必然是d//但是我们调整一下,去读取:bfseek(pf,-2,SEEK_CUR);//fseek(pf,1,SEEK_SET);ch = fgetc(pf);printf("%c\n",ch);//bfclose(pf);pf = NULL;}return 0;
}

5.2 ftell

返回文件指针相对于起始位置的偏移量(获取流中的当前位置)

long int ftell ( FILE * stream );

  • 返回流的位置指示器的当前值。
  • 对于二进制流
  • 这是从文件开头算起的字节数。
  • 对于文本流
  • 这个数值可能没有实际意义,但仍然可以使用 `fseek` 函数将位置恢复到相同的位置(如果有使用 `ungetc` 函数放回但尚未读取的字符,这种情况下行为是未定义的)。 
  • 操作成功时,将返回位置指示器的当前值。
  • 操作失败时,将返回 -1L,并将 `errno` 设置为一个系统特定的正值。 
int main()
{FILE* pf = fopen("test.txt","r");if(pf == NULL){perror("fopen");}else{int ch = fgetc(pf);printf("%c\n",ch);//ach = fgetc(pf);printf("%c\n",ch);//bch = fgetc(pf);printf("%c\n",ch);//c//如果继续往下读,必然是d//但是我们调整一下,去读取:bfseek(pf,-2,SEEK_CUR);//fseek(pf,1,SEEK_SET);ch = fgetc(pf);printf("%c\n",ch);//bprintf("%c\n",ftell(pf));//2fclose(pf);pf = NULL;}return 0;
}

5.3 rewind

让文件指针的位置回到文件的起始位置(将流的位置设置到文件开头)

void rewind ( FILE * stream );

int main()
{FILE* pf = fopen("test.txt","r");if(pf == NULL){perror("fopen");}else{int ch = fgetc(pf);printf("%c\n",ch);//ach = fgetc(pf);printf("%c\n",ch);//bch = fgetc(pf);printf("%c\n",ch);//c//如果继续往下读,必然是d//但是我们调整一下,去读取:bfseek(pf,-2,SEEK_CUR);//fseek(pf,1,SEEK_SET);ch = fgetc(pf);printf("%c\n",ch);//bprintf("%c\n",ftell(pf));//2rewind(pf);ch = fgetc(pf);printf("%c\n",ch);//afclose(pf);pf = NULL;}return 0;
}

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

根据数据的组织形式,数据文件被称为文本文件或者⼆进制文件

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

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

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

以ASCII形式存储:字符

int main()
{int a = 10000;FILE* pf = fopen("test.txt","w");fwrite(&a,4,1,pf);//二进制的形式写到文件中fclose(pf);pf = NULL;return 0;
}

我们将 test.txt 文件在VS中打开,会发现它是一串十六进制数字10 27 00 00

此时的存储方式是二进制形式存储,而为了方便表示,一般会转化为十六进制形式:

七、文件读取结束的判定

需要包含头文件 #include <stdio.h>

7.1 被错误使用的 feof

int feof ( FILE * stream );

如果与该流相关联的文件结束指示器已设置,则返回一个非零值。 否则,返回零。

牢记:在文件读取过程中,不能用feof函数的返回值直接来判断文件的是否结束。(文件结束标志 ---- EOF[-1])

feof 的作用是:当文件读取结束的时候,判断读取结束的原因是否是:遇到文件尾结束。(检查文件结束指示器)

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

例如:

• fgetc 判断是否为 EOF

• fgets 判断返回值是否为 NULL 

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

例如:

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

7.2  ferror

int ferror ( FILE * stream );

如果与该流相关联的错误指示器已设置,则返回一个非零值。否则,返回零值。

ferror 的作用是:当文件读取结束的时候,判断是读取结束的原因是否是:文件操作中发生了错误。(检查错误指示器)

文本文件例子:

//!pf 通常用于检查文件指针 pf 是否为 NULL,即判断文件是否成功打开或有效。
//! 是逻辑非运算符,用于对指针进行逻辑取反。
//当 pf 为 NULL 时,!pf 的值为 1(真),表示文件打开失败。
//当 pf 有效(非 NULL)时,!fp 的值为 0(假),表示文件已成功打开。
int main()
{int c;// 注意:int,⾮char,要求处理EOFFLIE* pf = fopen("test.txt","r");if(!pf) // 等价于 if (pf == NULL){perror("fopen");return 1;}//fgetc 当读取失败的时候或者遇到⽂件结束的时候,都会返回EOFwhile((c=fgetc(pf)) != EOF)// 标准C I/O读取⽂件循环{putchar(c);}//判断是什么原因结束的if(ferror(pf)) //返回真,就说明是文件在读取过程出错而结束printf("I/O error when reading");else if(feof(pf)) //返回真,就说明是文件正常读取遇到结束标志而结束printf("End of file reached successfully");fclose(pf);pf = NULL;return 0;
}

二进制文本例子:

enum {SIZE = 5};
int main()
{doublle a[SIZE] = {1,2,3,4,5};FILE* pf = fopen("test.txt","wb");// 必须⽤⼆进制模式fwrite(a,sizeof *a,SIZE,pf);// 写 double 的数组fclose(pf);double b[SIZE] = {0};pf = fopen("test.txt","rb");size_t ret = fread(b,sizeof *b,SIZE,pf);// 读 double 的数组if(ret == SIZE){int n = 0printf("Array read successfully, contents");for(n = 0;n < SIZE; n++){printf("%f ",b[n]);}}printf("\n");else{if(feof(pf))printf("Error reading text1.txt: unexpected end of file\n");else if(ferror(pf))printf("Error reading text1.txt");}fclose(pf);pf = NULL;return 0;
}

八、文件缓冲区

ANSIC 标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为 程序中每⼀个正在使用的文件开辟⼀块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓 冲区,装满缓冲区后才⼀起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。

#include <stdio.h>
#include <windows.h>
//VS2022 WIN11环境测试 
int main()
{FILE*pf = fopen("test.txt", "w");fputs("abcdef", pf);//先将代码放在输出缓冲区 printf("睡眠10秒-已经写数据了,打开test.txt⽂件,发现⽂件没有内容\n");Sleep(10000);printf("刷新缓冲区\n");fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到⽂件(磁盘) //注:fflush 在⾼版本的VS上不能使⽤了 printf("再睡眠10秒-此时,再次打开test.txt⽂件,⽂件有内容了\n");Sleep(10000);fclose(pf);//注:fclose在关闭⽂件的时候,也会刷新缓冲区 pf = NULL;return 0;
}

fflush —— 刷新缓冲区       fclose —— 关闭文件的时候也会刷新缓冲区

这里可以得出一个结论:

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

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

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

相关文章

react私有样式处理

react私有样式处理 Nav.jsx Menu.jsx vue中通过scoped来实现样式私有化。加上scoped&#xff0c;就属于当前组件的私有样式。 给视图中的元素都加了一个属性data-v-xxx&#xff0c;然后给这些样式都加上属性选择器。&#xff08;deep就是不加属性也不加属性选择器&#xff09; …

【信创-k8s】海光/兆芯+银河麒麟V10离线部署k8s1.31.8+kubesphere4.1.3

❝ KubeSphere V4已经开源半年多&#xff0c;而且v4.1.3也已经出来了&#xff0c;修复了众多bug。介于V4优秀的LuBan架构&#xff0c;核心组件非常少&#xff0c;资源占用也显著降低&#xff0c;同时带来众多功能和便利性。我们决定与时俱进&#xff0c;使用1.30版本的Kubernet…

单片机内部结构基础知识 FLASH相关解读

一、总线简单说明 地址总线、控制总线、数据总线 什么是8位8051框架结构的微控制器&#xff1f; 数据总线宽度为8位&#xff0c;即CPU一次处理或传输的数据量为8位&#xff08;1字节&#xff09; 同时还有一个16位的地址总线&#xff0c;这个地方也刚好对应了为什么能看到内存…

HTTPS加密的介绍

HTTPS&#xff08;HyperText Transfer Protocol Secure&#xff0c;超文本传输安全协议&#xff09;是HTTP协议的安全版本。它在HTTP的基础上加入了SSL/TLS协议&#xff0c;用于对数据进行加密&#xff0c;并确保数据传输过程中的机密性、完整性和身份验证。 在HTTPS出现之前&a…

【freertos-kernel】stream_buffer

文章目录 补充任务通知发送处理ulTaskGenericNotifyTakexTaskGenericNotifyWait 清除xTaskGenericNotifyStateClearulTaskGenericNotifyValueClear 结构体StreamBufferHandle_tStreamBufferCallbackFunction_t 创建xStreamBufferGenericCreatestream buffer的类型 删除vStreamB…

在word中点击zotero Add/Edit Citation没有反应的解决办法

重新安装了word插件 1.关掉word 2.进入Zotero左上角编辑-引用 3.往下滑找到Microsoft Word&#xff0c;点重新安装加载项

新华三H3CNE网络工程师认证—Easy IP

Easy IP 就是“用路由器自己的公网IP&#xff0c;给全家所有设备当共享门牌号”的技术&#xff01;&#xff08;省掉额外公网IP&#xff0c;省钱又省配置&#xff01;&#xff09; 生活场景对比&#xff0c;想象你住在一个小区&#xff1a;普通动态NAT&#xff1a;物业申请了 …

算法打开13天

41.前 K 个高频元素 &#xff08;力扣347题&#xff09; 给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 示例 1: 输入: nums [1,1,1,2,2,3], k 2 输出: [1,2]示例 2: 输入: nums [1], k 1 输出: …

LabVIEW与PLC液压泵测控系统

针对液压泵性能测试场景&#xff0c;采用LabVIEW与西门子 PLC 控制系统&#xff0c;构建高精度、高可靠性的智能测控系统。通过选用西门子 PLC、NI 数据采集卡、施耐德变频电机等&#xff0c;结合LabVIEW 强大的数据处理与界面开发能力&#xff0c;实现液压泵压力、流量、转速等…

应急响应靶机-web2-知攻善防实验室

题目&#xff1a; 前景需要&#xff1a;小李在某单位驻场值守&#xff0c;深夜12点&#xff0c;甲方已经回家了&#xff0c;小李刚偷偷摸鱼后&#xff0c;发现安全设备有告警&#xff0c;于是立刻停掉了机器开始排查。 这是他的服务器系统&#xff0c;请你找出以下内容&#…

Python制作史莱姆桌面宠物!可爱的

史莱姆桌面宠物 一个可爱的桌面史莱姆宠物&#xff0c;它会在您的任务栏上移动并提供可视化设置界面。 这里写目录标题 史莱姆桌面宠物功能特点安装与运行直接运行方式创建可执行文件 使用说明自定义GIF说明打包说明开源地址 功能特点 可爱的史莱姆在任务栏上自动移动支持…

vue3 自动导入自己的js文件中的函数

vue3 自动导入自己的js文件中的函数 vite.config.js import AutoImport from unplugin-auto-import/viteexport default defineConfig({resolve: {alias: {: fileURLToPath(new URL(./src, import.meta.url))}},plugins: [vue(),AutoImport({imports: [vue, vue-router, pini…

Mobile App UI自动化locator

在开展mobile app UI层自动化测试时&#xff0c;编写目标元素的locator是比较耗时的一个环节&#xff0c;弄清楚locator背后的逻辑&#xff0c;可以有效降低UI层测试维护成本。此篇博客以webdriverioappium作为UI自动化工具为例子&#xff0c;看看有哪些selector方法&#xff0…

44、web实验-后台管理系统基本功能

44、web实验-后台管理系统基本功能 “44、web实验-后台管理系统基本功能”通常指的是在Web开发学习过程中&#xff0c;关于构建后台管理系统的实践环节&#xff0c;主要涉及实现一个具备基本功能的后台管理系统。以下是该实验的主要内容&#xff1a; #### 实验目标 - 掌握后台管…

【Flask】:轻量级Python Web框架详解

什么是Flask&#xff1f; Flask是一个用Python编写的轻量级Web应用框架。它被称为"微框架"(microframework)&#xff0c;因为它核心简单但可扩展性强&#xff0c;不强制使用特定的项目结构或库。Flask由Armin Ronacher开发&#xff0c;基于Werkzeug WSGI工具包和Jin…

MAC电脑怎么通过触摸屏打开右键

在Mac电脑上&#xff0c;通过触摸屏打开右键菜单的方法如下&#xff1a; 法1:双指轻点&#xff1a;在触控板上同时用两根手指轻点&#xff0c;即可触发右键菜单。这是Mac上常用的右键操作方法。 法2:自定义触控板角落&#xff1a;可以设置触控板的右下角或左下角作为右键区域…

AI炼丹日志-26 - crawl4ai 专为 AI 打造的爬虫爬取库 上手指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇&#xff1a; MyBatis 更新完毕目前开始更新 Spring&#xff0c;一起深入浅出&#xff01; 大数据篇 300&#xff1a; Hadoop&…

java32

1.反射 获取类&#xff1a; 获取构造方法&#xff1a; 获取权限修饰符&#xff1a; 获取参数信息&#xff1a; 利用反射出来的构造器来创建对象&#xff1a; 获取成员变量&#xff1a; 获取成员方法&#xff1a; 综合练习&#xff1a; 动态代理&#xff1a;

OpenStack组件:放置服务(Placement)安装

OpenEuler的安装_openeuler5.1.0-249-CSDN博客 OpenStack云计算平台基础环境准备_openstack基础环境配置-CSDN博客 OpenStack组件&#xff1a;镜像服务&#xff08;Glance&#xff09;安装-CSDN博客 OpenStack组件&#xff1a;认证服务&#xff08;Keystone&#xff09;安装…

整合swagger,以及Knife4j优化界面

因为是前后端项目&#xff0c;需要前端的参与&#xff0c;所以一个好看的接口文档非常的重要 1、引入依赖 美化插件其中自带swagger的依赖了 <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-spring-boot-starter&…