C语言第三十七弹---文件操作(下)

个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】

文件操作

1、文件的随机读写

1.1、fseek

1.2、ftell

1.3、rewind

2、文件读取结束的判定

2.1、被错误使用的 feof

3、文件缓冲区

总结


1、文件的随机读写


1.1、fseek

根据文件指针的位置和偏移量来定位文件指针。
将与流关联的位置指示器设置为新位置。

对于以二进制模式打开的流,通过向原点指定的参考位置添加偏移来定义新位置。

对于以文本模式打开的流,偏移量应为零或上一次调用 ftell 返回的值,并且 origin 必须为SEEK_SET。

int fseek ( FILE * stream, long int offset, int origin );
//第一个参数是文件指针的名字(流)
//第二个参数是文件指针向后偏移数  可以为正数也可以为负数 正数为从前向后偏移  负数为从后先前偏移
//第三个参数是fseek函数中规定的三个选项之中的其一。
ConstantReference position  参考位置
SEEK_SETBeginning of file    //文件开头
SEEK_CURCurrent position of the file pointer  //文件当前位置
SEEK_ENDEnd of file *  //文件结尾

例子:
 

/* fseek example */
#include <stdio.h>int main ()
{
FILE * pFile;
pFile = fopen ( "example.txt" , "wb" );
fputs ( "This is an apple." , pFile );
fseek ( pFile , 9 , SEEK_SET );
fputs ( " sam" , pFile );
fclose ( pFile );
return 0;
}

为什么最后在记事本中打印出的结果是This is a sample.呢?

原因是在第一次fputs中是把This is an apple.先放入记事本当中,当调用fseek函数时,从当前的文件指针处向后偏移9个字节,文件指针一开始默认指向的是文件的首地址处。因此向后偏移9个字节后(偏移一个字节包括空格)指向的是a之后的位置。而第二次fputs函数是将“ sam”这个内容在上次文件指针指向的地址处开始写入。因此在记事本打印的结果是This is a sample.

1.2、ftell

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

long int ftell ( FILE * stream );
//参数为指向标识流的 FILE 对象的指针。

例子:
 

/* ftell example : getting size of a file */
#include <stdio.h>
int main ()
{
FILE * pFile;
long size;
pFile = fopen ("myfile.txt","rb");
if (pFile==NULL)
perror ("Error opening file");
else
{
fseek (pFile, 0, SEEK_END); // non-portable
size=ftell (pFile);
fclose (pFile);
printf ("Size of myfile.txt: %ld bytes.\n",size);
}
return 0;
}

因为是从文件内容的最末尾处开始相对于起始位置的偏移量。则结果为17。

1.3、rewind

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

void rewind ( FILE * stream );

例子:
 

/* rewind example */
#include <stdio.h>
int main ()
{
int n;
FILE * pFile;
char buffer [27];
pFile = fopen ("myfile.txt","w+");
for ( n='A' ; n<='Z' ; n++)
fputc ( n, pFile);//将26个大写字母传入文件流
rewind (pFile);//将文件指针移动到文件开头
fread (buffer,1,26,pFile);//将文件流数据传入buffer字符数组
fclose (pFile);
buffer[26]='\0';
printf(buffer);//打印字符数组
return 0;
}

代码输出结果:

2、文件读取结束的判定


2.1、被错误使用的 feof


牢记:在文件读取过程中,不能用feof函数的返回值直接来判断文件的是否结束。


feof 的作用是:当文件读取结束的时候,判断是读取结束的原因是否是:遇到文件尾结束。


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

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


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

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


文本文件的例子:
 

#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);
}

二进制文件的例子:
 

#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 handling
if (feof(fp))
printf("Error reading test.bin: unexpected end of file\n");
else if (ferror(fp)) {
perror("Error reading test.bin");
}
}
fclose(fp);
}

3、文件缓冲区


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

 

#include <stdio.h>
#include <windows.h>
//VS2019 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;
}

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

总结


本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!

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

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

相关文章

typescript学习(更新中)

目录 开发环境搭建类型如何声明有哪些类型编译配置文件 开发环境搭建 npm i -g typescripttsc检查是否安装成功 类型如何声明 // 先声明再赋值 let a: number a 1// 直接赋值 let b 1function sum(a: number, b: number): number {return a b } console.log(sum(1, 2))有…

VSCode搭建ARM开发环境

为了构建Cortex M系列单片机免费开源的开发环境&#xff0c;网络上了解来看VSCODEGCCJLINK是一套比较高效的组合方式&#xff0c;下面记录环境搭建的流程。 我这边的PC环境为 WIN7专业版64bit。 需要用到的工具 Visual Studio CodeSTM32CubemxARM GCC 交叉编译工具链&#x…

【刷题记录】详谈设计循环队列

下题目为个人的刷题记录&#xff0c;在本节博客中我将详细谈论设计循环队列的思路&#xff0c;并给出代码&#xff0c;有需要借鉴即可。 题目&#xff1a;LINK 循环队列是线性表吗&#xff1f;或者说循环队列是线性结构吗&#xff1f; 对于这个问题&#xff0c;我们来看一下线…

Vue 项目性能优化指南:提升应用速度与效率

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Qt插件之输入法插件的构建和使用(二)

文章目录 主键盘搭建Google开源引擎音节分割工具类参考项目下载搭建好各个基础控件之后,就可以开发输入法的主界面和引擎了,这也是输入法的核心。 主键盘搭建 输入法的主界面本质上是一个QStackedWidget容器,将各个类型的输入键盘插入到容器中,然后根据业务需要切换不同的…

图机器学习(4)-面向连接层面的人工特征工程

0 问题定义 通过已经连接去猜未知连接&#xff1a; 有两个思路&#xff1a; &#xff08;1&#xff09;直接提取link的特征&#xff0c;把link变成D维向量&#xff1b; &#xff08;2&#xff09;把link两端节点的D维向量拼在一起&#xff0c;缺点&#xff1a;丢失了link本身…

蓝桥省赛倒计时 35 天-线性 dp 练习

文章目录 数学三角形最长上升子序列 数学三角形 思路&#xff1a;就是下一层通过上一层的条件转移过来&#xff0c;注意数可以是负数&#xff0c;所以边界得取-INF&#xff0c;这样求上层 max 的时候不会被初始化的数如 0 影响。 #include<bits/stdc.h> using namespace…

md5绕过

文章目录 \\和\\\md5数组绕过科学计数法绕过双md加密md5碰撞Hash长度攻击 下面会以同一道题给大家演示&#xff1a; (题目来源与nssctf) 和 在php代码中我们会看到和&#xff0c;虽然两个都是表示相等&#xff0c;但是在细节上会有所部区别 &#xff1a;是弱比较&#xff0c;只…

美团春招编程第一场第三题

美团春招编程第一场第三题 题目 解答 思路-暴力解法 pair中存储从原点到包含当前元素的0,1数量&#xff0c;得到二维数组mat; 从头到尾遍历尺寸为i*i的矩形&#xff0c;计算完美矩形数量 #include <iostream> #include <vector> using namespace std;int main()…

【项目】Boost 搜索引擎

文章目录 1.背景2.宏观原理3.相关技术与开发环境4. 实现原理1.下载2.加载与解析文件2.1获取指定目录下的所有网页文件2.2. 获取网页文件中的关键信息2.3. 对读取文件进行保存 3.索引3.1正排与倒排3.2获取正排和倒排索引3.3建立索引3.3.1正排索引3.3.2倒排索引 4.搜索4.1 初始化…

Linux Docker安装redis缓存数据库

文章目录 一、查找Redis镜像二、拉取redis镜像三、创建数据目录和配置文件四、创建redis容器 一、查找Redis镜像 首先到docker镜像仓库下载redis镜像。地址&#xff1a;https://hub.docker.com/搜索redis&#xff0c;如下&#xff1a;找到对应想要下载的版本&#xff1a; 二、…

Win11 没有网络bug

1.问题描述 没有网络&#xff0c;dns一直是固定的&#xff0c;但是dns已经是自动获取了(MAC地址随机) 2.解决办法 1.首先&#xff0c;删除所有网络的手动dns配置,控制中心那个dns管理没有用,在设置中删除网络,不然问题还会出现 - 2.然后&#xff0c;进入注册表\HKEY_LOCAL_MACH…

产品推荐 - 基于6U VPX的双TMS320C6678+Xilinx FPGA K7 XC7K420T的图像信号处理板

综合图像处理硬件平台包括图像信号处理板2块&#xff0c;视频处理板1块&#xff0c;主控板1块&#xff0c;电源板1块&#xff0c;VPX背板1块。 一、板卡概述 图像信号处理板包括2片TI 多核DSP处理器-TMS320C6678&#xff0c;1片Xilinx FPGA XC7K420T-1FFG1156&#xff0c;1片…

kafka(三)springboot集成kafka(1)介绍

基于kafka新版本 <dependencies><dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId><version>3.0.0</version></dependency> </dependencies> 一、kafkaProducer 1、介绍…

数据结构与算法-哈希表

引言 在计算机科学中&#xff0c;数据结构与算法是构建高效软件系统的关键基石。其中&#xff0c;哈希表作为一种非常实用的数据结构&#xff0c;以其快速查找、插入和删除等特性&#xff0c;在诸多领域发挥着无可替代的作用。本文将深入探讨哈希表的工作原理、实现细节以及其在…

ChatGPT 升级出现「我们未能验证您的支付方式/we are unable to authenticate」怎么办?

ChatGPT 升级出现「我们未能验证您的支付方式/we are unable to authenticate」怎么办&#xff1f; 在订阅 ChatGPT Plus 时&#xff0c;有时候会出现以下报错 &#xff1a; We are unable to authenticate your payment method. 我们未能验证您的支付方式。 出现 unable to a…

Springboot+vue的物业管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的物业管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目。 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的物业管理系统&#xff0c;采用M&#xff08;model&#xff09;V&#xff…

Open3D 生成空间3D椭圆点云

目录 一、算法原理二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法原理 设椭圆在 X O Y XOY XO

Unity性能优化篇(七) UI优化注意事项以及使用Sprite Atlas打包精灵图集

UI优化注意事项 1.尽量避免使用IMGUI(OnGUI)来做游戏时的UI&#xff0c;因为IMGUI的开销比较大。 2.如果一个UGUI的控件不需要进行射线检测&#xff0c;则可以取消勾选Raycast Target 3.尽量避免使用完全透明的图片和UI控件。因为即使完全透明&#xff0c;我们看不见它&#xf…

基于GitBucket的Hook构建ES检索PDF等文档全栈方案

背景 之前已简单使用ES及Kibana和在线转Base64工具实现了检索文档的demo&#xff0c;预期建设方案是使用触发器类型从公共的文档源拉取最新的文件&#xff0c;然后调用Java将文件转Base64后入ES建索引&#xff0c;再提供封装接口给前端做查询之用。 由于全部内容过长&#xff…