【c语言进阶】文件操作(下)

news2024/9/24 23:26:43

在这里插入图片描述

🚀write in front🚀
📜所属专栏: c语言学习
🛰️博客主页:睿睿的博客主页
🛰️代码仓库:🎉VS2022_C语言仓库
🎡您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!
关注我,关注我,关注我你们将会看到更多的优质内容!!

在这里插入图片描述

文章目录

  • 前言
  • 一、文件的随机读写
    • 1、fseek函数:
    • 2、ftell函数:
    • 3、rewind函数:
    • 4、综合使用:
  • 二、文本文件与二进制文件:
  • 三、文件结束的判定:
    • 1.错误使用 feof 函数:
    • 2.一些判断文件结束的总结:
      • 2.1. 文本文件读取是否结束:
      • 2.2. 二进制文件的读取结束判断,
    • 3.判断原因的两个函数:
  • 四、缓冲区的简单介绍
  • 总结:

前言

  在上一篇文章中上一篇文章文件操作知识大全(上),我们学习了文件操作的相关知识,比如顺序读写,文件的打开与关闭,文件指针等等。今天我们再来补充一些常用的知识点!

一、文件的随机读写

1、fseek函数:

根据文件指针的位置和偏移量来定位文件指针

函数格式:

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

注意事项:

  • 其中“ offset ”为相对于指针位置的指针偏移量
  • 其中“ origin ”为指针位置,其参数有三种:
    SEEK_CUR ”表示文件指针当前位置
    SEEK_END ”表示文件末尾的位置
    SEEK_SET ”表示文件开始位置
int main()
{
	FILE* pf = fopen("test.txt", "w");
	fputs("abcd", pf);
	fclose(pf);
	pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
	}
	else
	{
		int ch = fgetc(pf);
		printf("%c\n", ch);//a
		ch = fgetc(pf);
		printf("%c\n", ch);//b
		ch = fgetc(pf);
		printf("%c\n", ch);//c

		//如果继续往下读,必然是d
		//但是我们调整一下,去读取:b
		//fseek(pf, -2, SEEK_CUR);
		fseek(pf, 1, SEEK_SET);
		ch = fgetc(pf);
		printf("%c\n", ch);//b
	}

	return 0;
}

运行结果:

在这里插入图片描述

2、ftell函数:

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

函数格式:

long int ftell(FILE* stream);

3、rewind函数:

让文件指针的位置回到文件的起始位置(其实相当于fseek(stream,0,SIZE_SET))

函数格式:

void rewind(FILE* strname);

4、综合使用:

int main()
{
	FILE* pf = fopen("test.txt", "w");
	fputs("abcd", pf);
	fclose(pf);
	pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
	}
	else
	{
		int ch = fgetc(pf);
		printf("%c\n", ch);//a
		ch = fgetc(pf);
		printf("%c\n", ch);//b
		ch = fgetc(pf);
		printf("%c\n", ch);//c

		//如果继续往下读,必然是d
		//但是我们调整一下,去读取:b
		//fseek(pf, -2, SEEK_CUR);
		fseek(pf, 1, SEEK_SET);
		ch = fgetc(pf);
		printf("偏移一个字符后是%c\n", ch);//b
		printf("总共便宜了%d\n个位置", ftell(pf));
		rewind(pf);
		ch = fgetc(pf);
		printf("回到起始位置后是%c\n", ch);//a
	}

	return 0;
}

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

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

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

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

int main()
{
	int a = 10000;
	FILE* p = fopen("test.txt", "wb");
	//“wb”表示以只写模式打开二进制文件
	if (p == NULL)
	{
		perror("FileOpen");
		return 0;
	}
	fwrite(&a, 4, 1, p);
	//将变量a中的数据,每四个字节存储一次,写入文件指针p所指向的文件
 
	fclose(p);
	p = NULL;
 
	return 0;
}

通过文本文件发现看不懂:
在这里插入图片描述
  其实原因大家都知道,我们是以2进制的形式传进去的,文本文件就以这个2进制打印了字符。所以我们现在来用二进制形式看看该文件(16进制)!
在这里插入图片描述

在这里插入图片描述

每四个字节进行划分:
0000 0000 0000 0000 0010 0111 0001 0000
于是得到:
00 00 27 10

  又因为我们的vs是小端存储,于是在进行压栈时会将数据进行倒置存储,于是就有了该结果。

三、文件结束的判定:

1.错误使用 feof 函数:

  在一段时间的交流中,我发现有很多小伙伴们都错误的使用feof 函数将其用于判断文件是否读取结束 ,而这种使用方式是错误的

我们应该记住:

  • 在文件的读取过程中,不能通过 feof 函数的返回值来判定文件是否读取结束
  • 该函数的作用为:在已经确定文件读取结束的情况下用于判定文件读取结束的原因

2.一些判断文件结束的总结:

2.1. 文本文件读取是否结束:

要判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )
例如:
fgetc 判断是否为 EOF .
fgets 判断返回值是否为 NULL .

int main()
{
    int c; 
    //注意:int,非char,要求处理EOF
    FILE* fp = fopen("test.txt", "r");
    if (!fp)
    {
        perror("File opening failed");
        return 1;
    }
    // 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);
    fp = NULL;
 
	return 0;
}

2.2. 二进制文件的读取结束判断,

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

#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);
    fp = NULL;
    return 0;
}

3.判断原因的两个函数:

在这里插入图片描述

四、缓冲区的简单介绍

  文件缓冲区是用以暂时存放读写期间的文件数据而在内存区预留的一定空间
  ANSIC 标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”.从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。
在这里插入图片描述
  要使缓冲区的内容进入内存或者计算机硬盘有两种方法,第一种是缓冲区充满自动填入,第二个是主动刷新缓冲区。

在这里插入图片描述

举个例子:

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

  所以在这里,各位小伙伴们一定要注意了,因为缓冲区的存在,数据只有在填满缓冲区后才会进行真正的写入或读取,所以在 C 语言程序代码的编写过程中,我们一定要在文件操作结束时关闭文件,否则就可能导致文件的读写操作出现问题。

总结:

  经过今天内容的补充,我们关于文件操作与管理的知识就全部学完了,不知道小伙伴们是否掌握了呢?
  更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

专栏订阅:
每日一题
c语言学习
算法
智力题
更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

在这里插入图片描述

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

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

相关文章

[NOIP2008 提高组] 笨小猴

题目描述 笨小猴的词汇量很小&#xff0c;所以每次做英语选择题的时候都很头疼。但是他找到了一种方法&#xff0c;经试验证明&#xff0c;用这种方法去选择选项的时候选对的几率非常大&#xff01; 这种方法的具体描述如下&#xff1a;假设 maxn 是单词中出现次数最多的字母的…

Python 中当前时间表示方法详解

在 Python 中获取当前时间是许多与时间有关的操作的一个很好的起点。一个非常重要的用例是创建时间戳。在本教程中&#xff0c;你将学习如何用 datetime 模块获取、显示和格式化当前时间。我们将学习如何读取当前时间的属性&#xff0c;如年份、分钟或秒。为了使时间更容易阅读…

函数的求导法则——“高等数学”

今天&#xff0c;小雅兰的内容是函数的求导法则&#xff0c;上篇博客我们知道了导数的定义、导数的几何意义及可导与连续关系&#xff0c;这篇博客我们来仔细学习一下求导法则&#xff0c;下面&#xff0c;就让我们进入导数的世界吧 一、函数的和、差、积、商的求导法则 二、反…

Beryl Li 代表 YGG 出席 2023 年世界经济论坛会议

Yield Guild Games&#xff08;YGG&#xff09;联合创始人 Beryl Li 代表 YGG 参加了 2023 年 1 月 16 日至 20 日在瑞士达沃斯举行的 2023 年世界经济论坛年会 &#xff08;WEF23&#xff09;&#xff0c;在全球舞台上分享区块链、通证化、数字资产监管、治理和价值创造的潜力…

C++语法复习笔记-4. C++基本容器

文章目录1.数组声明与定义数组的开闭区间差一错误左闭右开非对称区间原则数组的增删改查一维数组二维数组面向对象的动态数组-vector自动扩容增删改查2. 字符串字符串变量与常量unicode编码字符串指针表示方法指针的表示方法char[]和char* 的区别数组每个值可改指针指向的字符串…

Yann LeCun 新作!大幅超越 MAE,图像语义表示卷出新高度

文&#xff5c;CV酱计算机视觉中&#xff0c;有两种常见的从图像中进行自我监督学习的方法&#xff1a;基于不变性的方法和生成方法。基于不变性的预训练方法优化编码器&#xff0c;使其产生相似的嵌入&#xff0c;用于同一图像的两个或多个视图&#xff0c;其中图像视图通常使…

基于Java+Spring的图书管理系统详细设计和实现

博主介绍&#xff1a;✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

【项目精选】基于Web的机票预订系统

文章目录 1 摘 要2 系统相关技术概述2.1 Java web2.2 三大框架SSM2.3 前端框架AngularJS2.4 数据库MySQL2.5 数据库Redis2.6 开发工具Eclipse 3 需求分析3.1 系统实现目标3.2 系统功能分析3.3 系统用列图 4 系统总体设计4.1 软件架构设计4.2 总体功能模块设计4.3 数据库设计4…

python小游戏——怀念经典坦克大战代码

♥️作者&#xff1a;小刘在这里 ♥️每天分享云计算网络运维课堂笔记&#xff0c;努力不一定有收获&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的&#xff0c;绽放&#xff0c;愿所有的美好&#…

14.集合、泛型、List系列

目录 一.集合类的体系结构 1.1 Collection体系 1.2 Map集合体系 1.3 集合的注意事项 二.泛型 2.1 什么是泛型 2.2 泛型的优点 2.3 泛型可以在哪些地方上定义 2.4 泛型类 2.5 泛型方法 2.6 泛型接口 2.7 泛型通配符 三.Collection集合 3.1 什么是Collection集合 3…

CentOS7没有图形化界面,怎么安装图形化界面

我们在安装CentOS7时&#xff0c;如果选择 “最小化” 安装那么系统就只有命令行界面&#xff0c;但是没有图形化界面&#xff0c;如下图&#xff1a; 解决的完整步骤如下&#xff1a; 1&#xff09;开启CentOS7并登录root用户&#xff08;一定要以root用户登录&#xff0c;其…

windows电脑生成ios证书的方法

在uniapp开发进行云打包的时候&#xff0c;打包Ios应用需要p12格式的私钥证书和证书profile文件。无论使用windows电脑&#xff0c;还是mac电脑&#xff0c;生成ios证书&#xff0c;需要苹果开发者账号&#xff0c;假如你还没有苹果开发者账号&#xff0c;你可以参考下文先到苹…

「跨界选手」郭莎莎:我是怎么从服装设计转向智能家居的

作者 | 牧之 编辑 | 小沐 出品 | 智哪儿 zhinaer.cn最近几年&#xff0c;全国各地都在上演智能家居创业热。尤其是很多年轻人&#xff0c;从不同的行业转战而来。他们拥有不同的背景、认知和经验&#xff0c;为智能家居的线下渠道注入了多元活力。而本期「智哪儿」专访的采访对…

vue前端框架课程笔记(四)

目录vue中的内置指令v-textv-htmlv-cloakv-oncev-pre汇总自定义指令全局指令与局部指令使用示例生命周期问题引入生命周期函数简介钩子函数图示过程生命周期函数示例本博客参考尚硅谷官方课程&#xff0c;详细请参考 【尚硅谷bilibili官方】 本博客以vue2作为学习目标&#x…

新公链的加速孵化器有哪些值得期待?

媒体、工程师技术支持、VC、机构投资者&#xff0c;有经验的创业者等。Moonbeam Accelerator团结各方力量&#xff0c;帮助创业者做更好的领导者。 Web3的发展瞬息万变&#xff0c;包括Moonbeam自己也在未知的领域探索。作为区块链创业者&#xff0c;我们都有自己固定的思维和…

【redis6】第十一章(秒杀案例)

计数器和人员记录 秒杀页面 <% page language"java" contentType"text/html; charsetUTF-8"pageEncoding"UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loo…

RocketMQ5.0.0消息发送

一、消息消息实体类为org.apache.rocketmq.common.message.Message&#xff0c;其主要属性如下。// 消息所属topic private String topic; // 消息Flag&#xff08;RocketMQ不作处理&#xff09;&#xff0c;即&#xff1a;用户处理 private int flag; // 扩展属性 private Map…

零代码实现EDI标准报文转换

在与客户进行沟通的时候&#xff0c;经常有客户对EDI实施很感兴趣&#xff0c;一方面是客户具有相应的IT基础和技术力量&#xff0c;并且后续可能会有更多合作伙伴的EDI接入&#xff0c;因此客户有自主实施的想法&#xff1b;另一方面也可以在一定程度上为企业节约成本。 知行…

谷歌seo排名需要的链接数量?谷歌seo排名需要多久?

本文主要分享要实现谷歌排名需要多少条英文外链&#xff0c;以及时间成本的预估。 本文由光算创作&#xff0c;有可能会被修改或剽窃&#xff0c;我们佛系对待这种行为吧。 谷歌seo排名需要的链接数量是多少&#xff1f; 答案是&#xff1a;需要1000~2000条GPB外链 为什么一…

对数据中台的梳理与思考

Gartmer:《数据中台在中国已经接近炒作的顶峰》 PowerData&#xff1a;接近顶峰?那就说明还有上升的空间嘛 本篇文章聊聊数据中台爆火背后的逻辑。 一、概念篇 1、什么是中台 中台是将系统的通用化能力进行打包整合&#xff0c;通过接口的形式赋能到外部系统&#xff0c;从而…