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

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

目录 

✨前言✨

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

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

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

🧧总结🧧

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

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

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

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: 数据库