【C语言】文件操作揭秘:C语言中文件的顺序读写、随机读写、判断文件结束和文件缓冲区详细解析【图文详解】

news2024/11/24 8:49:13

欢迎来CILMY23的博客喔,本篇为【C语言】文件操作揭秘:C语言中文件的顺序读写、随机读写、判断文件结束和文件缓冲区详细解析【图文详解】,感谢观看,支持的可以给个一键三连,点赞关注+收藏。

前言 

欢迎来到本篇博客,上一篇我们详细介绍C语言中的文件操作。

在计算机领域,文件是一种常见的存储和处理信息的方式。通过文件,我们可以将数据和程序永久保存在硬盘中,并随时读取和修改。本篇博客将深入探讨文件操作、文件的顺序读写、随机读写、判断文件结束和文件缓冲区详细解析。

上一篇博客链接:

【C语言】文件操作篇-----程序文件和数据文件,文件的打开和关闭,二进制文件和文本文件,fopen,fclose【图文详解】-CSDN博客

文章目录

一、文件的顺序读写

1.1 文件顺序读写的函数介绍:

 1.2 fgetc和fputc的使用

1.3 fgets和fputs的使用

1.4 fprintf和printf的使用 

1.5 fscanf和scanf的使用 

1.6 sscanf和sprintf的介绍和使用 

1.7 fwrite和fread的使用 

1.8 总结

二、文件的随机读写

2.1 fseek函数 

 2.2 ftell函数

三、文件读取结束的判定

四、文件缓冲区 


一、文件的顺序读写

文件顺序读写是指按照数据在文件中的顺序依次读取或写入数据的操作方式。在文件顺序读写中,数据按照其存储在文件中的顺序被逐个读取或写入。

对于顺序读取,程序会依次读取文件中的数据,从文件的开头一直读取到末尾,直到到达文件结束的位置或者读取到所需的数据为止。每次读取数据后,读取指针会自动向后移动到下一个数据的位置。

对于顺序写入,程序会依次将数据写入文件,从文件的结尾开始写入,每写入一个数据后,写入指针会自动移动到下一个位置,以便写入下一个数据。这样,数据会按照写入的顺序依次添加到文件中。

1.1 文件顺序读写的函数介绍:

 上面说的使用于所有输入流⼀般指使用于标准输入流和其他输入流(如文件输入流);所有输出流⼀般指使用于标准输出流和其他输出流(如文件输出流)。

fgetc 和 fputc: 这两个函数用于逐个字符地读取和写入文件。(一次读取(写入)一个)

它们的原型如下:

int fgetc(FILE *stream);
int fputc(int character, FILE *stream);

fgets:从指定文件中读取一行数据(包括换行符),并将其存储到指定的字符数组中。

原型如下:

char *fgets(char *str, int n, FILE *stream);

fputs:将指定的字符串写入到指定文件中。(一次写一行数据)

原型如下:

int fputs(const char *str, FILE *stream);

fscanf: 该函数用于从文件中按照指定的格式读取数据。

它的原型如下:

int fscanf(FILE *stream, const char *format, ...);

fprintf: 该函数用于向文件中按照指定的格式写入数据。

它的原型如下:

int fprintf(FILE *stream, const char *format, ...);

fread函数:

  • 函数原型:
    size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
  • 功能:从指定文件中读取二进制数据,并将其存储到指定的内存位置。
  • 参数:
    • ptr:指向存储读取的数据的内存位置的指针。
    • size:每个数据项的字节数。
    • count:要读取的数据项的个数。
    • stream:指向已打开文件的指针,表示从该文件中读取数据。
  • 返回值:返回实际成功读取的数据项数目,如果返回值少于count,则可能表示已到达文件末尾或发生了错误。

fwrite函数:

  • 函数原型:
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
  • 功能:将二进制数据写入指定文件中。
  • 参数:
    • ptr:指向要写入的数据的内存位置的指针。
    • size:每个数据项的字节数。
    • count:要写入的数据项的个数。
    • stream:指向已打开文件的指针,表示将数据写入到该文件中。
  • 返回值:返回实际成功写入的数据项数目,如果返回值少于count,则可能表示发生了错误。

 1.2 fgetc和fputc的使用

我们现在在当前路径下:C:\Users\云山若汐\source\repos\test2\test2

放入两个文件, 

write可以不放,然后我们在text中输入abcd,我们现在将要拷贝当中的字符到write中,所以写下以下代码:

#include<stdio.h>

int main()
{
	char ch;
	FILE* pfread = fopen("text.txt", "r");
	if (pfread == NULL)
	{
		perror("fopen - 1");
		return 1;
	}
	FILE* pfwrite = fopen("write.txt", "w");
	if (pfwrite == NULL)
	{
		perror("fopen - 2");
		return 1;
	}

	while ((ch = fgetc(pfread)) != EOF)
	{
		fputc(ch, pfwrite);
	}
	fclose(pfread);
	pfread = NULL;
	fclose(pfwrite);
	pfwrite = NULL;
}

效果如下: 

1.3 fgets和fputs的使用

假设此时text中有两行,它们分别是:

 

int main()
{
	char arr[20];

	FILE* pf = fopen("text.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	
	fgets(arr, 20, pf);
	printf("%s", arr);

	fclose(pf);
	pf = NULL;

	return 0;
}

我们使用fgets从文件中获取信息,注意fgets只会从指定文件中读取一行数据(包括换行符)也就是换行符是固定的,我们读取20只会读取前十九个字符因为最后一个字符要存放换行符。

1.4 fprintf和printf的使用 

 假设我们定义了一个结构体如下所示,那我们可以使用printf将其打印到屏幕上,也可以使用fprintf将其打印至屏幕上,或者将其写入文件中

struct S
{
	int n;
	float f;
	char arr[100];
};

int main()
{
	struct S s = { 100,3.14f,"zhangsan" };

	FILE* pf = fopen("text.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	//输出到屏幕上
	printf("%d %f %s\n", s.n, s.f, s.arr);
	fprintf(stdout, "%d %f %s", s.n, s.f, s.arr);
	//使用fprintf输出到文件中
	fprintf(pf, "%d %f %s\n", s.n, s.f, s.arr);

	fclose(pf);
	pf = NULL;

	return 0;
}

效果如下:

1.5 fscanf和scanf的使用 

struct S
{
	int n;
	float f;
	char arr[100];
};

int main()
{
	struct S s = {0};

	FILE* pf = fopen("text.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	
	fscanf(pf,"%d %f %s",&(s.n), &(s.f), &(s.arr));
	printf("%d %f %s", s.n, s.f, s.arr);

	fclose(pf);
	pf = NULL;

	return 0;
}

 我们用"fopen"打开一个名为"text.txt"的文件来读取数据。如果打开成功,你使用"fscanf"函数从文件中读取整数、浮点数和字符串,存储到结构体"s"的相应成员中。注意,在"%s"格式符后,使用"s.arr"而不是"&"操作符(因为数组名本身就是数组的首地址)

1.6 sscanf和sprintf的介绍和使用 

在本文中,我们将介绍C++中两个常用的输入输出解析函数:sscanf和sprintf。这两个函数提供了灵活的方式来处理字符串和变量之间的格式化输入输出操作。

  • sscanf函数:
    • sscanf函数用于将字符串按照指定的格式解析,并将解析后的值存储到对应的变量中。
    • 语法:int sscanf(const char* str, const char* format, ...)
    • str为输入的字符串,format为格式化字符串,...为对应的变量列表。
#include <stdio.h>

int main() {
   const char* str = "23.5 10";
   float f;
   int i;
   sscanf(str, "%f %d", &f, &i);

   printf("解析出的浮点数为:%.2f\n", f);
   printf("解析出的整数为:%d\n", i);

   return 0;
}
  • sprintf函数:
    • sprintf函数用于将格式化的数据输出到字符串中。
    • 语法:int sprintf(char* str, const char* format, ...)
    • str为输出的字符串,format为格式化字符串,...为对应的变量列表。
#include <stdio.h>

int main() {
   char str[100];
   int i = 42;
   float f = 3.14;

   sprintf(str, "整数:%d,浮点数:%.2f", i, f);

   printf("格式化后的字符串:%s\n", str);

   return 0;
}

sscanf和sprintf函数是C语言中常用的输入输出解析函数,可以方便地进行字符串的解析和格式化输出

1.7 fwrite和fread的使用 

 fwrite的使用

#include <stdio.h>

int main()
{
    int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    FILE* pf = fopen("text.txt", "wb");
    if (pf == NULL)
    {
        perror("fopen");
        return 1;
    }

    fwrite(arr, sizeof(int), 10, pf); // 写入整个数组

    fclose(pf);
    pf = NULL;

    return 0;
}

我们可以在项目中用二进制形式查看这个txt文件 ,右键该文件,选择打开方式,选择底部的二进制编辑器,

 ​​​​​

 我们可以看到文件中写入了几个数

那如何验证我们是否写入了呢?这时候我们就需要用到fread

int main()
{
    int arr[10] = {0};

    FILE* pf = fopen("text.txt", "rb");
    if (pf == NULL)
    {
        perror("fopen");
        return 1;
    }

    fread(arr, sizeof(int), 10, pf); 
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        printf("%d ", arr[i]);
    }

    fclose(pf);
    pf = NULL;

    return 0;
}

1.8 总结

二、文件的随机读写

C语言中的随机读写通常指的是以随机的方式访问文件中的数据,而不是按顺序逐个读取或写入。这种随机的读写通常涉及到文件指针的定位,可以根据需要在文件中的不同位置进行读写操作。

 C语言提供了两个函数来进行文件的随机读写,它们分别是fseek和ftell

2.1 fseek函数 

fseek - C++ Reference (cplusplus.com)

  • fseek 函数:

    • 函数原型:
    • int fseek ( FILE * stream, long int offset, int origin );
    • 功能:移动文件流中的读写位置,进行随机的文件定位。
    • 参数:
      • stream:指向文件的指针。
      • offset:偏移量,用于指定文件指针要移动的位置。
      • origin:指定起始位置,可以取三个值:
      • SEEK_SET :文件的开始位置
      • SEEK_CUR:文件指针的当前位置
      • SEEK_END:文件的末尾位置
    • 返回值:如果成功,返回0;否则,返回非0值(通常是-1)。

fseek的使用,fseek函数主要有三种origin的起始值 

 至于偏移量就是距离我的origin有多远了,从1字节开始算

例如:

假设我的text里存了CILMY23

#include <stdio.h>

int main()
{

    FILE* pf = fopen("text.txt", "r");
    if (pf == NULL)
    {
        perror("fopen");
        return 1;
    }
    fseek(pf, 0, SEEK_SET);//C
    char ch = fgetc(pf);
    printf("%c\n", ch);

    fseek(pf, -1, SEEK_END);//3
    ch = fgetc(pf);
    printf("%c\n", ch);

    fseek(pf, -5, SEEK_CUR);//L
    ch = fgetc(pf);
    printf("%c\n", ch);

    fclose(pf);
    pf = NULL;

    return 0;
}

 2.2 ftell函数

 ftell - C++ Reference (cplusplus.com)

 ftell函数:

  • 原型:
    long int ftell ( FILE * stream );
  • 功能:获取当前文件位置指针的偏移字节数。
  • 参数:
    • stream:指向文件的指针。
  • 返回值:返回当前文件位置指针的偏移字节数。

例如: 

#include <stdio.h>

int main()
{

    FILE* pf = fopen("text.txt", "r");
    if (pf == NULL)
    {
        perror("fopen");
        return 1;
    }

    fseek(pf, -1, SEEK_END);//3
    char ch = fgetc(pf);
    printf("%c\n", ch);

    int ret = ftell(pf);
    printf("%d", ret);

    fclose(pf);
    pf = NULL;

    return 0;
}

三、文件读取结束的判定

文件读取结束可以通过feof函数进行判定。feof函数用于检测文件流上的结束标志。当文件末尾已经读取,feof函数返回非零值;否则返回0。

文件读取结束的原因可能有:

1.文件遇到末尾

2.文件发生错误

#include<stdio.h>

int main()
{
    FILE* pf = fopen("text.txt", "r");
    if (pf == NULL)
    {
        perror("fopen");
        return 1;
    }

    int ch;
    while ((ch = fgetc(pf)) != EOF)
    {
        // 处理读取的字符
        if (feof(pf))
        {
            printf("文件读取结束\n");
        }
        else
        {
            printf("文件读取出错\n");
        }
    }
    fclose(pf);
    pf = NULL;
    return 0;
}

 所以在文件读取过程中,不能用feof函数的返回值直接来判断文件的是否结束。feof 的作用是:当文件读取结束的时候,判断是读取结束的原因是否是:遇到文件末尾结束

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

例如:
•       fgetc 判断是否为  EOF .
•       fgets 判断返回值是否为NULL .
2.    二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。 例如:
•    fread判断返回值是否小于实际要读的个数。

四、文件缓冲区 

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

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

通过本篇博客,相信你了解了C语言中文件操作的核心内容。文件的顺序读写、随机读写、文件读取结束的判定以及文件缓冲区等知识点,感谢你的阅读!如果你对文件操作还有任何疑问或需要进一步的帮助,请随时留言,如果你觉得还不错的话,可以给个一键三连,点赞关注加收藏,本篇博客就到此结束了。

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

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

相关文章

Linux编程4.9 网络编程-建立连接

1、TCP的连接与断开 三次握手与四次挥手 2、服务器端并发性处理 2.1 多进程模型 一个父进程&#xff0c;多个子进程父进程负责等待并接受客户端连接子进程: 完成通信&#xff0c;接受一个客户端连接&#xff0c;就创建一个子进程用于通信。 2.2 多线程模型 多线程服务器是…

Vue3+.NET6前后端分离式管理后台实战(四)

1&#xff0c;Vue3.NET6前后端分离式管理后台实战(四)已经发布&#xff0c; 程序源码已打包&#xff0c;感兴趣的可以关注下载。 2&#xff0c;源码打包可以下载&#xff1a;

整合qq邮箱发送

目录 &#x1f32e;1.获取qq授权码 &#x1fad3;2.引入依赖 &#x1f9c8;3.配置mail信息 &#x1f95e;4.创建实现类 &#x1f956;5.测试 1.获取qq授权码 点击开启服务&#xff0c;发送信息获取授权码 2.引入依赖 <!--邮件--><dependency><groupId&…

FL Studio for Mac 21.2.3.3586中文版的一些特点

FL Studio&#xff08;Fruity Loops&#xff09;是一款非常流行的数字音乐工作站软件&#xff0c;它可以让用户轻松地制作各种类型的音乐。前不久&#xff0c;FL Studio发布了最新的Mac版21.2.3.3586中文版&#xff0c;这个新版本的发布让广大Mac用户感到非常兴奋。本文将介绍F…

OSI(Open Systems Interconnection)网络架构模型简介

OSI&#xff08;Open Systems Interconnection&#xff09;参考模型是一种概念性的网络架构模型&#xff0c;它将计算机通信系统划分为7个层次&#xff0c;每个层次都有自己的功能和职责&#xff0c;通过相互合作来实现整个网络的通信。这7个层次分别是&#xff1a; 应用层&…

刷力扣看见一个寻找单身狗的问题?【力扣题解】

今天刷力扣遇到一道有意思的题目&#xff0c;题目是写着撞色问题177 &#xff0c;当我写完这个题去看看有什么好的解题方式的时候&#xff0c;看见一个有趣的题解问题&#xff0c;他对这个题目的描述是几对情侣&#xff0c;带几个单身狗出去玩&#xff0c;然后现在我们要把这几…

Android分区存储到底该怎么做

文章目录 一、Android存储结构二、什么是分区存储&#xff1f;三、私有目录和公有目录三、存储权限和分区存储有什么关系&#xff1f;四、我们应该该怎么做适配&#xff1f;4.1、利用File进行操作4.2、使用MediaStore操作数据库 一、Android存储结构 Android存储分为内部存储和…

AI算力池化赋能企业大模型价值探索

1. 大语言模型企业落地中的算力痛点 随着人工智能技术的飞速发展&#xff0c;自然语言处理&#xff08;NLP&#xff09;成为了热门的研究领域之一。在这一领域中&#xff0c;大语言模型&#xff08;Large Language Models&#xff09;凭借其强大的语言理解和生成能力&#xff…

ArcGIS Pro、R与INVEST的多技术融合:生态系统服务权衡与协同研究的新纪元

生态系统服务是指生态系统所形成的用于维持人类赖以生存和发展的自然环境条件与效用&#xff0c;是人类直接或间接从生态系统中得到的各种惠益。联合国千年生态系统评估&#xff08;Millennium ecosystem assessment&#xff0c;MA&#xff09;提出生态系统服务包括供给、调节、…

突发!OpenAI服务异常!!!

2024/3/20傍晚7点&#xff0c;笔者的朋友在使用OpenAI时&#xff0c;页面提示服务异常&#xff0c;由此引发了我的深思&#xff1a;人工智能的脆弱性与未来的挑战 2024年3月20日&#xff0c;傍晚7点&#xff0c;一个普通的周二&#xff0c;我的朋友在尝试使用OpenAI时&#xf…

媒体发稿途径,怎么样去网络媒体投稿,媒体发布一般价格多少钱?

在信息爆炸的时代&#xff0c;媒体作为传递信息的重要渠道&#xff0c;成为企业推广的重要手段。然而&#xff0c;如何去网络媒体投稿&#xff0c;以及媒体发布的价格却是困扰很多企业和个人的问题。今天&#xff0c;我们将会为大家介绍一种简单易行的方式&#xff1a;媒介多多…

vue3 几种实现点击复制链接的方法

vue3 几种实现点击复制链接的方法 环境&#xff1a;vue3tselment plus 目的&#xff1a;常用到的地方就是点击复制分享链接功能 1.复制当前页面链接&#xff0c; <template><div class"news" style"margin-top: 30px"><el-button type&q…

事务同步管理器TransactionSynchronizationManager

事务同步管理器的使用场景&#xff1a; 同步涉及的资源包括&#xff1a;SqlSession & Connection。同步资源核心目的是线程共享&#xff0c;意味着必须跟线程绑定。同步资源伴随着线程生存或者消亡&#xff0c;意味着线程结束之前必须手动清除其绑定的资源。事务同步管理器…

Swift 从获取所有 NSObject 对象聊起:ObjC、汇编语言以及底层方法调用链(一)

概览 Swift 语言给我们的印象是&#xff1a;简洁、现代化和可以“心安神泰”的完全信赖。不过&#xff0c;在一些特殊情况下我们唯有进入 Swift 底层的动态世界方能真正地“随遇而安”。 保安局“刘局长”曾语重心长的教导过我们&#xff1a;“非常时期&#xff0c;用非常方法…

MATLAB环境下基于机器学习的合成数据生成方法

合成数据是通过计算机程序人工生成的数据&#xff0c;而不是由真实事件生成的数据。采用合成数据来增加训练数据&#xff0c;可以节省数据采集费用&#xff0c;或满足隐私要求。随着计算能力的提高和云数据存储选项的崛起&#xff0c;合成数据比以往更容易获取。这无疑是一个积…

VO、RVO、ORCA(动态避障)算法

碰撞锥&#xff08;碰撞区域&#xff09; 上上图中假设B物体处于静止状态&#xff0c;A物体沿着向量v1和v2移动&#xff0c;刚好能和B擦肩而过&#xff0c;不会发生碰撞&#xff1b;若V1和V2的夹角再小一点的话就一定会发生碰撞。此时会产生碰撞区域&#xff1a; 红线画出来…

学生信息管理系统--修改信息(非常详细的修改,更新,撤销,删除逻辑)

目录 概述修改包括的操作修改在每个模块中的应用 详解修改与更新取消删除 特殊概念数据集游标 总结 概述 学生信息管理系统&#xff0c;功能相对简单且代码重复性高&#xff0c;应该采用复用的思想来减少代码的冗余和提高代码的可维护性。然而&#xff0c;对于基础入门项目来说…

【Web APIs】DOM获取元素

目录 1.Web API基本认识 2.获取DOM元素 3.设置/修改DOM元素内容 4.设置/修改DOM元素属性 4.1修改元素常用属性 4.2修改元素样式属性 4.3设置/修改表单属性 5.定时器-间歇函数 1.Web API基本认识 作用&#xff1a;就是使用js去操作html和浏览器 分类&#xff1a;DOM&am…

一网打尽音乐制作!FL Studio21.2.3中文版全能数字音频工作站

一网打尽音乐制作&#xff01;FL Studio21中文版全能数字音频工作站&#xff0c;专业机构力荐 &#xff1a;打造专业音乐制作&#xff0c;让音乐梦想触手可及&#xff01; FL Studio是一款广泛使用的数字音频工作站&#xff0c;被许多音乐制作人和DJ用来制作和混合音乐。最新版…

基于torch.compile和gptfast代码风格实现ChatGLM模型推理加速

目录 一、ChatGLM模型代码重构迁移 二、推理的代码重构 三、效果分析对比 参考文章 torch2.0发布以后模型训练和推理可以实现一行代码加速&#xff0c;试用之后发现效果并不明显。随后gptfast项目也发布&#xff0c;表明它确实是可以实现模型推理的加速&#xff0c;看来之前…