【C语言进阶】速学,不会用数据库可不能再错过文本与二进制文件操作

news2024/9/23 13:29:05

目录

✨前言✨:

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

🎁二、文件读取结束的判定🎁:

        1.错误使用 feof 函数:

        2.判断文件读取结束:

🎊三、文件缓冲区🎊:

🧧总结🧧:


🛰️博客主页:✈️銮同学的干货分享基地

🛰️欢迎关注:👍点赞🙌收藏✍️留言

🛰️系列专栏:💐【进阶】C语言学习

                       🧧  C语言学习

🛰️代码仓库:🎉VS2022_C语言仓库

        家人们更新不易,你们的👍点赞👍和⭐关注⭐真的对我真重要,各位路过的友友麻烦多多点赞关注,欢迎你们的私信提问,感谢你们的转发!

        关注我,关注我,关注我,你们将会看到更多的优质内容!!


🏡🏡 本文重点 🏡🏡:

🚅文本与二进制文件🚃文件读取结束判定🚃文件缓冲区🚏🚏

✨前言✨:

        在上节课中我们已经学习了有关本地磁盘文件的常用文件操作,已经能够对本地文件进行调用与读写操作,能够将数据写入本地磁盘,也能够从本地调用数据。同时在上节课中我们也提到过,在我们的磁盘内还存在着一些二进制文件,于是我们今天就再来研究一下文本文件与二进制文件操作的细节

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

        根据数据的组织形式,我们将数据文件称为文本文件二进制文件

        我们之前在研究各种量的时候就提到过,在我们的计算机内存中,各种数据都是以二进制码的形式进行存储的,而如果这时数据不加转换就向外输出至外存,就是二进制文件

        如此便是二进制文件,而如果我们想要在外存上以 ASCII 码的形式存储数据,就需要在存储前将数据进行转换。而这种以 ASCII 字符形式进行存储的文件,就是文本文件

        那么数据在内存中数据到底是如何让进行存储的呢?

        实际上,字符在内存中的存储一律是以 ASCII 码的形式进行存储的,而数值型数据既可以用ASCII 码存储,也可以用二进制形式进行存储

        例如十进制数字 10000 在进行存储时,就可以有两种存储形式

★ 二进制形式:

        00000000 00000000 00100111 00010000

★ ASCII码形式:

00110001001100000011000000110000000110000
10000

        我们还是来看实例

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

        在上面这段代码运行成功后,我们已经成功的将变量 a 中的数据写入到了本地磁盘对应的 txt 文件中了,可是我们发现,当我们尝试打开本地文件查看存储的数据时,里面看起来并不是我们想要的结果:

        难道是我们的程序哪里出错了吗?其实并不是,而是因为我们使用了" wb "方式,即以二进制形式进行了写入,所以我们在尝试直接查看时显示的是二进制符号

        所以我们就需要换一种方式才能对我们的文件内容进行查看。首先选中我们的“ 源文件 ”栏,右击选择“ 添加 ” → “ 添加现有项 ”,将写入时创建的 txt 文件添加进来:

        然后选中 txt 文件,右击选择“ 打开方式 ”选项

        接着在选项框中下拉选择“ 二进制编辑器 ”

        这时我们就看到了文件内的实际存储情况了:

        它显示我们的文件中的实际存储数据为 10 27 00 00,这又是怎么来的呢?这是因为,我们在存储时根据语句:

fwrite(&a, 4, 1, p);

        根据这条语句,我们在进行数据写入时,是四个字节四个字节进行写入的,于是根据其二进制码可以得到它的存储为

每四个字节进行划分:

        0000 0000 0000 0000 0010 0111 0001 0000

于是得到:

        00 00 27 10

        又因为在之前我们就验证过我的计算机采用的是小端存储模式,于是在进行压栈时会将数据进行倒置存储,于是就有:

10 27 00 00

        至此,就得到了我们写入文件中的实际数据内容

🎁二、文件读取结束的判定🎁:

        1.错误使用 feof 函数:

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

        各位小伙伴们一定要牢记

在文件的读取过程中,不能通过 feof 函数的返回值来判定文件是否读取结束

该函数的作用为,在已经确定文件读取结束的情况下,用于判定文件读取结束的原因

        2.判断文件读取结束:

        那么我们该如何判断文件是否读取结束了呢?

        文本文件判断文件读取结束方法:

①. 使用 fgetc 函数判断是否为 EOF。

②. 使用 fgets 函数判断返回值是否为 NULL。

        例如:

#include<stdio.h>
#include<stdlib.h>

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

        ★ 二进制文件判断文件读取结束方法:

使用 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;
}

🎊三、文件缓冲区🎊:

        文件缓冲区是用以暂时存放读写期间的文件数据而在内存区预留的一定空间。通过磁盘缓存 来实现,磁盘缓存本身并不是一种实际存在的存储介质,它依托于固定磁盘,提供对主存储器存储空间的扩充,即利用主存中的存储空间, 来暂存从磁盘中读出 (或写入)的信息

        例如在国际 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 语言程序代码的编写过程中,在对文件进行操作时,需要刷新缓冲区并在文件操作结束时关闭文件,否则就可能导致文件的读写操作出现问题

🧧总结🧧:

        经过今天内容的补充,我们关于文件操作与管理的知识就全部学完了,不知道各位小伙伴们究竟又掌握了多少呢?这一部分的内容在我们还没有学习数据库的现阶段来说较为实用,可以帮助我们调用和读写本地文件,能够帮助我们将程序运行中产生的有用的数据保存至本地,也能大批量的从本地对数据进行导入。希望各位小伙伴们在闲暇时间中能够多加练习,夯实基础,为后来的学习做好坚实的铺垫,为了明天成为更好的自己埋下基石!

        🔥🔥一生中你唯一需要回头的时候,是为了看自己到底走了多远🔥🔥

        更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~  你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

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

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

相关文章

Ubuntu虚拟机图文安装详细教程

Hello, 小伙伴们&#xff0c;大家好&#xff01;今天教大家一步一步进行ubuntu虚拟机的安装。俗话说的好&#xff1a;“工欲善其事必先利其器”&#xff0c;作为一名嵌入式软件开发人员&#xff0c;我们必须熟悉Linux系统的操作及使用&#xff0c;熟练掌握Linux系统下的开发&am…

java 接口的私有方法

其实java8就已经做下伏笔了 在拥有静态和默认 两种拥有方法体的方法之后 接口出现私有方法也是一种必然 然后我们来创建一个包 包下创建一个接口 subInterface 参考代码如下 public interface subInterface {private void show2() {System.out.println("我是一个私有方…

头条权重在线查询,头条号增加权重的4个妙招

头条号权重可以简单理解为头条号指数&#xff0c;刚开通头条号的时候&#xff0c;会根据头条号的领域、介绍等等给予相应的权重。后期会根据账号使用情况进行调整权重&#xff0c;提高或者降低。 头条权重在线查询方法 打开“站长工具”之后&#xff0c;输入网站网址。…

LeetCodeday04

24. 两两交换链表中的节点 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3…

JavaScript篇.day08-DOM,节点,事件,定时器,位置及坐标

目录 1.DOM 2.DOM相关操作 (1)获取元素 (2)操作元素 (3)操作元素属性 (4)操作元素类名 (5)操作元素样式 3.节点操作 4.事件 5.事件传播 6.定时器 7.位置及坐标 1.DOM Document Object Model 文档对象模型一整套操作文档流相关内容的属性和方法可以做的操作: 修改样…

前端框架搭建(六)搭建页面框架【vite】

1.安装所需依赖 需要安装 vue-routernaive视图框架 npm npm install vue-router4 yarn yarn add vue-router4npm i -D naive-ui2.搭建naive适配框架 创建文件夹——存放通用组件 在components下创建文件夹common 全局配置常用组件 在之前创建的global.d.ts中添加Window…

枚举的应用

枚举&#xff1a; 在数学和计算机科学理论中&#xff0c;一个集的枚举是列出某些有穷序列集的所有成员的程序&#xff0c;或者是一种特定类型对象的计数。这两种类型经常&#xff08;但不总是&#xff09;重叠。 [1] 是一个被命名的整型常数的集合&#xff0c;枚举在日常生活…

基于CAS操作的atomic原子类型

原子操作 C A S (compare And Swap&#xff09;也叫比较交换&#xff0c;是一种无锁原子算法&#xff0c;映射到操作系统就是一条cmpxchg硬件汇编指令&#xff08;保证原子性)&#xff0c;其作用是让CPU将内存值更新为新值&#xff0c;但是有个条件&#xff0c;内存值必须与期望…

站长权重在线查询,怎么查询网站权重是多少?

什么是网站权重 当站长们辛辛苦苦建立起来一个网站&#xff0c;怎么才能知道自己的网站在搜索引擎中的权重情况呢&#xff1f; 对于很多人而言&#xff0c;权重这个词可能听到最多的场景就是淘宝京东店铺权重。淘宝或京东会根据商家网店的浏览量、好评率、转化率、是否…

4A(统一安全管控平台)解析

4A是指帐号&#xff08;Account&#xff09;、认证&#xff08;Authentication&#xff09;、授权&#xff08;Authorization&#xff09;和审计&#xff08;Audit&#xff09;&#xff0c;4A统一安全管控平台是以身份为中心&#xff0c;实现帐号、认证、授权和审计统一管控的安…

Spark注意事项

一、Spark理解 数据的操作只有两种 大数据领域中对数据的操作只有两种:聚合 & 处理 无论是多华丽算法,最终都是这两个平平无奇的操作组合而成的 action理解 在spark中,一个action操作为一个jobId(在源码中可以看到runjob 是只有在action操作后才会调用) , 所以一个…

Mac内存空间不足导致无法安装Ventura?可用这些方法释放储存空间

安装Macos新版系统Ventura需要非常多的内存空间&#xff0c;本身我们的Mac磁盘空间就掣襟肘见&#xff0c;我们又该如何释放Mac磁盘空间来安装Ventura呢&#xff1f;今日&#xff0c;小编将分享一些能够释放大量Mac内存空间的方法&#xff0c;以便大家能够优化Mac的运行速度外还…

摄影基础笔记

https://www.icourse163.org/learn/UESTC-1001958013?tid1450439527#/learn/content 这里写目录标题景深 焦距 光圈视角快门测光 感光度构图井字曝光色温白平衡光光的强度光的方向色彩色相明度饱和度色相环反差影调手机瞬间后期处理景深 焦距 光圈 当我们把镜头对着一个景物聚…

Annoconda常见用法

打开conda命令行窗口 点击开始&#xff0c;选择A-选择Anaconda里面的prompt 查看环境 conda env list #查看虚拟环境 创建环境 conda create -n 虚拟环境名字 python3.8 #创建虚拟环境 python3.8 指定python版本 激活环境 conda activate 虚拟环境名字 #进入虚拟环境 …

Linux磁盘情况常用查看指令

Linux磁盘情况 磁盘查询 df -h&#xff1a;(disk free)查询磁盘的整体情况。 du -h&#xff1a;(disk usage)查询指定目录的磁盘占用情况&#xff0c;默认为当前目录 -s 指定目录占用大小汇总-h 带计量单位-a 含文件–max-depth1 子目录深度-c 列出明细的同时&#xff0c;增…

【LDF】线性判别函数(二)

感知准则函数 线性可分性 现有 nnn 个 样本: y1,y2,…,yn\mathbf{y}_1, \mathbf{y}_2, \ldots, \mathbf{y}_ny1​,y2​,…,yn​, 这些样本来自于两个类别 ω1\omega_1ω1​ 或 ω2\omega_2ω2​ 。任务: 寻找一个线性判别函数 g(x)aTyg(\mathbf{x})\mathbf{a}^T \mathbf{y}g(…

SpringMVC 入门案例

1.1 添加依赖 在pom文件中添加 javax.servlet-api 和 spring-webmvc 依赖&#xff1b; javax.servlet-api&#xff1a;主要用于 JAVA Web 开发&#xff1b; spring-webmvc&#xff1a;SpringMVC 依赖&#xff1b; <dependencies><dependency><groupId>javax.…

Xilinx ZYNQ 7000 AXI GPIO 读写/中断

打开SDK 后&#xff0c;创建官方例程 打开官方例程后&#xff0c;会发现这个AXI GPIO设置和 PS MIO/EMIO一模一样 int main(void) {int Status;volatile int Delay;/* Initialize the GPIO driver */Status XGpio_Initialize(&Gpio, GPIO_EXAMPLE_DEVICE_ID);if (Status…

unity-概念与实操入门

文章目录编译器推荐&#xff08;Rider&#xff09;坐标世界坐标系相对坐标系资源商店快捷入口地面制作脚本新建脚本生命周期vs测试打印对象标签&#xff08;自带集合属性&#xff09;图层预设体创建预设体&#xff08;cocos相同&#xff09;定位预设体文件位置预设体添加、更新…

python第一次作业

目录 1.下列程序运行结果为&#xff1a; 2.下列程序运行结果为&#xff1a; 3.下列程序运行结果为&#xff1a; 4.下列程序运行结果为&#xff1a; 5.编写程序&#xff1a;从键盘输入两个两位数&#xff0c;组成一个新的四位数&#xff0c; 6.编写程序功能如下&#xff1a…