【C语言】文件操作(三)

news2025/2/23 18:14:53

在这里插入图片描述

前言
在文件操作(二)中我们学习了顺序读写文件的函数,在这篇博客中我们将学习⽂件的随机读写,⽂件读取结束的判定。

文章目录

  • 一、文件的随机读写
    • 1.1 fseek
    • 1.2 ftell
    • 1.3 rewind
  • 二、文件读取结束的判定
    • 2.1 ferror和feof
  • 三、文件缓冲区

一、文件的随机读写

1.1 fseek

fseek 函数允许您在文件中移动文件指针到指定位置。这是进行随机访问的基础,因为您可以使用 fseek 定位到文件中的任何位置,并从那里进行读取或写入。

int fseek(FILE *stream, long int offset, int whence)
参数:
stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了流。
offset -- 这是相对 whence 的偏移量,以字节为单位。
whence -- 参照点,可以是 SEEK_SET(从文件开始位置开始移动),
          SEEK_CUR(从当前位置开始移动),
          或 SEEK_END(从文件末尾开始移动)。

返回值:
如果成功,则该函数返回零,否则返回非零值。
#include <stdio.h>
int main(){
	FILE* pFile;
	pFile = fopen("example.txt", "wb");//
	fputs("This is an apple.", pFile);//将"This is an apple."写入文件
	fseek(pFile, 9, SEEK_SET);//文件指针从文本开头,偏移量为9,最终指向‘n’
	fputs(" sam", pFile);//将" sam"写入文件
	fclose(pFile);
	return 0;
}

运行结果:
在这里插入图片描述


1.2 ftell

ftell 函数用于获取当前文件指针的位置,以字节为单位。这可用于记录当前位置以便稍后进行恢复。

long int ftell(FILE *stream)
参数
stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了流。

返回值
ftell 函数的返回值是当前文件指针的位置偏移量,以字节为单位,从文件的开头开始计算。
#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "r");
    
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    long position;
    char buffer[256];

    // 获取当前文件指针位置
    position = ftell(file);
    printf("当前文件指针位置:%ld\n", position);

    // 读取文件的一部分数据
    fgets(buffer, sizeof(buffer), file);
    printf("读取的数据:%s\n", buffer);

    // 获取新的文件指针位置
    position = ftell(file);
    printf("当前文件指针位置:%ld\n", position);

    // 将文件指针重新定位到之前记录的位置
    fseek(file, position, SEEK_SET);

    // 再次读取相同的数据
    fgets(buffer, sizeof(buffer), file);
    printf("再次读取的数据:%s", buffer);

    fclose(file);

    return 0;
}

新建文件:
在这里插入图片描述
运行结果:
在这里插入图片描述


1.3 rewind

rewind 函数用于将文件指针重新定位到文件的开头,等效于使用 fseek(file, 0, SEEK_SET)。

void rewind(FILE *stream);
#include <stdio.h>

int main() {
    FILE* file = fopen("example.txt", "r");

    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    char buffer[256];

    // 读取文件的一部分数据
    fgets(buffer, sizeof(buffer), file);
    printf("读取的数据:%s\n", buffer);

    // 将文件指针重新定位到文件的开头
    rewind(file);

    // 再次读取文件的一部分数据(与之前相同的数据)
    fgets(buffer, sizeof(buffer), file);
    printf("再次读取的数据:%s", buffer);

    fclose(file);

    return 0;
}

新建文件:
在这里插入图片描述

运行结果:
在这里插入图片描述


二、文件读取结束的判定

2.1 ferror和feof

ferror 和 feof 是C标准库中用于处理文件流错误的两个函数,它们用于检测文件操作时可能发生的错误和文件流的结束。下面是它们的详细解释:

  1. ferror 函数
  • ferror(file error)函数用于检测文件流中是否发生了错误。它的原型如下:
int ferror(FILE *stream);
如果在之前的文件操作中发生了错误,ferror 函数将返回非零值(通常是1),表示文件流出现了错误。
否则,它将返回零,表示没有错误发生。
  1. feof 函数
  • feof(end of file)函数用于检测文件流是否已到达文件的结束。它的原型如下:
int feof(FILE *stream);
如果文件流已经到达文件的结束位置,feof 函数将返回非零值(通常是1),表示已经到达文件末尾。
否则,它将返回零,表示文件流尚未到达文件末尾。

实例:

#include <stdio.h>
#include <stdlib.h>
int main(void){
	int c; // 注意:int,⾮char,要求处理EOF
	FILE* fp = fopen("test.txt", "r");
	if (!fp) {
		perror("文件打开失败");
		//EXIT_FAILURE 是一个标准的宏定义,通常表示程序以非正常状态退出。
		return EXIT_FAILURE;
	}
	
	//fgetc 当读取失败的时候或者遇到⽂件结束的时候,都会返回EOF
	while ((c = fgetc(fp)) != EOF) {
		putchar(c);
	}
	printf("\n");
	
	//判断是什么原因结束的
	if (ferror(fp))
		puts("读取数据时发生了输入/输出错误");
	else if (feof(fp))
		puts("文件内容到达文件末尾");
	fclose(fp);
}

新建文件:
在这里插入图片描述
运行结果:
在这里插入图片描述


三、文件缓冲区

文件缓冲区是在文件输入/输出操作期间用于临时存储数据的内存区域。它有助于提高文件操作的效率,减少了频繁的磁盘访问,因为磁盘访问通常比内存访问慢得多。

文件缓冲区的工作方式如下:

  1. 缓冲区的创建:在打开文件时,C标准库会为文件分配一个默认大小的缓冲区(通常是一块内存区域)。这个缓冲区称为文件缓冲区或流缓冲区。

  2. 缓冲模式:文件可以处于不同的缓冲模式下,主要有两种模式:

    • 全缓冲:文件的输入/输出操作完全在缓冲区中进行,直到缓冲区满或刷新时才将数据写入磁盘或从磁盘读取数据。
    • 行缓冲:文件的输入/输出操作以行为单位进行,当遇到换行符 \n 时才刷新缓冲区。通常用于文本文件。
      可以使用 setvbuf 函数来更改缓冲模式。
  3. 缓冲操作:当进行文件输入(如读取数据)时,数据首先被读入文件缓冲区。当进行文件输出(如写入数据)时,数据首先被写入文件缓冲区。

  4. 刷新缓冲区:缓冲区的数据可以在以下情况下被刷新(即写入磁盘或从磁盘读取):

    • 显式调用 fflush 函数。
    • 缓冲区满了(对于全缓冲模式)。
    • 遇到换行符 \n(对于行缓冲模式)。
  5. 关闭文件:当关闭文件时,文件缓冲区中的剩余数据通常会被刷新到磁盘。

示例:

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "w");

    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    // 写入数据到文件缓冲区
    fprintf(file, "这是一行文本\n");

    // 关闭文件,缓冲区的数据会被刷新到磁盘
    fclose(file);

    return 0;
}

在上面的示例中,尽管我们在 fprintf 函数中写入了数据,但只有在 fclose 函数被调用时,数据才会被写入磁盘。这是因为关闭文件时会触发缓冲区的刷新操作。如果需要立即将数据写入磁盘,可以在 fprintf 后调用 fflush 函数。

结论
因为有缓冲区的存在,C语⾔在操作⽂件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。


在这里插入图片描述
如果你喜欢这篇文章,点赞👍+评论+关注⭐️哦!
欢迎大家提出疑问,以及不同的见解。

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

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

相关文章

键盘上F1至F12键的作用

多年来&#xff0c;我们习惯了最上排的12个按键&#xff0c;从F1到F12&#xff0c;它们被称为“快速功能键”&#xff0c;可以让你更轻松地操作电脑&#xff1b;但是&#xff0c;很多人可能从未使用过它们&#xff0c;也从来不知道它们的用途。那么今天&#xff0c;就向大家科普…

【Pytorch笔记】4.梯度计算

深度之眼官方账号 - 01-04-mp4-计算图与动态图机制 前置知识&#xff1a;计算图 可以参考我的笔记&#xff1a; 【学习笔记】计算机视觉与深度学习(2.全连接神经网络) 计算图 以这棵计算图为例。这个计算图中&#xff0c;叶子节点为x和w。 import torchw torch.tensor([1.]…

web漏洞-PHP反序列化

目录 PHP反序列化序列化反序列化原理涉及技术利用危害CTF靶场 PHP反序列化 序列化 将对象转换成字符串 反序列化 相反&#xff0c;将字符串转换成对象。 数据格式的转换对象的序列化有利于对象的保存和传输&#xff0c;也可以让多个文件共享对象。 原理 未对用户输入的序列化字…

使用关键字interface来声明使用接口-PHP8知识详解

继承特性简化了对象、类的创建&#xff0c;增加了代码的可重用性。但是php8只支持单继承&#xff0c;如果想实现多继承&#xff0c;就需要使用接口。PHP8可以实现多个接口。 接口类通过关键字interface来声明&#xff0c;接口中不能声明变量&#xff0c;只能使用关键字const声明…

vcomp120.dll丢失的详细解决方法,全面分享5个解决方法分享

vcomp120.dll 是 Visual C Redistributable 的一个组件&#xff0c;是许多 Windows 应用程序所必需的动态链接库 (DLL) 之一。如果计算机上缺少 vcomp120.dll 文件&#xff0c;或者该文件已损坏或不正确&#xff0c;可能会导致许多应用程序无法正常运行&#xff0c;出现“无法继…

openGauss学习笔记-88 openGauss 数据库管理-内存优化表MOT管理-内存表特性-使用MOT-MOT使用将磁盘表转换为MOT

文章目录 openGauss学习笔记-88 openGauss 数据库管理-内存优化表MOT管理-内存表特性-使用MOT-MOT使用将磁盘表转换为MOT88.1 前置条件检查88.2 转换88.3 转换示例 openGauss学习笔记-88 openGauss 数据库管理-内存优化表MOT管理-内存表特性-使用MOT-MOT使用将磁盘表转换为MOT …

数据挖掘实验(一)数据规范化【最小-最大规范化、零-均值规范化、小数定标规范化】

一、数据规范化的原理 数据规范化处理是数据挖掘的一项基础工作。不同的属性变量往往具有不同的取值范围&#xff0c;数值间的差别可能很大&#xff0c;不进行处理可能会影响到数据分析的结果。为了消除指标之间由于取值范围带来的差异&#xff0c;需要进行标准化处理。将数据…

Linux系统编程系列之线程的信号处理

一、为什么要有线程的信号处理 由于多线程程序中线程的执行状态是并发的&#xff0c;因此当一个进程收到一个信号时&#xff0c;那么究竟由进程中的哪条线程响应这个信号就是不确定的&#xff0c;只能取决于哪条线程刚好在信号达到的瞬间被调度&#xff0c;这种不确定性在程序逻…

java学生成绩管理信息系统

一、 引言 学生成绩管理信息系统是一个基于Java Swing的桌面应用程序&#xff0c;旨在方便学校、老师和学生对学生成绩进行管理和查询。本文档将提供系统的详细说明&#xff0c;包括系统特性、使用方法和技术实现。 二、 系统特性 2.1 学生管理 添加学生信息&#xff1a;录…

基于SSM农产品商城系统

基于SSM农产品商城系统的设计与实现&#xff0c;前后端分离&#xff0c;文档 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringSpringMVCMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 农产品列表 产品详情 个人中心 登陆界面 管…

gici-open示例数据运行(1.1开阔环境数据运行)

1、配置数据和处理模式 下载对应的数据集后&#xff0c;首先处理1.1中的开阔环境下数据&#xff0c;将option目录下的配置文件复制到1.1数据目录下&#xff08;若采用ROS编译&#xff0c;则配置文件目录为ros_wrapper/src/gici/option/ros real time estimation xxx.yaml&…

Fiddle日常运用手册(2)-使用过滤器进行接口精准拦截

关于Fiddle的基础界面大家已经了解&#xff0c;日常工作中可以进行简单的抓包和数据分析了。 但是&#xff0c;工作中我们又会发现&#xff0c;单纯的进行批量抓包会抓取很多无效的心跳接口数据导致让我们漏掉一些重要信息。那么如果我们想精准的拦截某一个IP的接口交互数据&am…

231003-四步MacOS-iPadOS设置无线竖屏随航SideCar

Step 0&#xff1a;MacOS到iPad无线竖屏随航显示&#xff0c;最终效果 Step 1&#xff1a; 下载 Better Display Step 2&#xff1a;在设置中新建虚拟屏幕&#xff0c;创建虚拟屏幕 Step 3&#xff1a;进行如下设置 Step 4&#xff1a;注意事项 ⚠️ 设置后的虚拟屏幕与Sideca…

基于SSM的餐厅点菜管理系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

找不到VCRUNTIME140_1.dll怎么办,VCRUNTIME140_1.dll丢失的5个解决方法

在当今的数字时代&#xff0c;我们的生活和工作都离不开电脑。然而&#xff0c;随着科技的发展&#xff0c;我们也会遇到各种各样的问题。其中&#xff0c;VCRUNTIME140_1.dll丢失的问题是许多人都会遇到的困扰。这个问题可能会导致许多应用程序无法正常运行&#xff0c;给我们…

如何在 Google Earth 中创建轨迹、路线并制作动画

如何创建航迹 https://kurviger.de/en Google 地球飞行教程(天桥动画) 选择合适的点 &#xff08;可调整视图快照&#xff09;点击录制&#xff0c;依次点击图标即可

电子计算机核心发展(继电器-真空管-晶体管)

目录 继电器 最大的机电计算机之一——哈弗Mark1号&#xff0c;IBM1944年 背景 组成 性能 核心——继电器 简介 缺点 速度 齿轮磨损 Bug的由来 真空管诞生 组成 控制开关电流 继电器对比 磨损 速度 缺点 影响 代表 第一个可编程计算机 第一个真正通用&am…

Go 代码中的文档和注释

撰写清晰、简洁和全面的代码文档的指南 在软件开发领域&#xff0c;编写代码只占了一半的战斗。另一半则围绕着创建清晰、简洁和全面的文档展开&#xff0c;这些文档不仅有助于开发人员理解代码库&#xff0c;还充当未来开发的路线图。在本指南中&#xff0c;我们将深入探讨编…

蓝桥杯每日一题2023.10.3

杨辉三角形 - 蓝桥云课 (lanqiao.cn) 题目描述 题目分析 40分写法&#xff1a; 可以自己手动构造一个杨辉三角&#xff0c;然后进行循环&#xff0c;用cnt记录下循环数的个数&#xff0c;看哪个数与要找的数一样&#xff0c;输出cnt #include<bits/stdc.h> using na…

协议栈——收发数据(拼接网络包,自动重发,滑动窗口机制)

目录 协议栈何时发送数据&#xff5e; 数据长度 IP模块的分片功能 发送频率 网络包序号&#xff5e;利用syn拼接网络包ack确认网络包完整 确定偏移量 服务器ack确定收到数据总长度 序号作用 双端告知各自序号 协议栈自动重发机制 大致流程 ack等待时间如何调整 是…