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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Mybatis之自定义映射resultMap

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

Qualcomm AI Hub-示例(三)模型推理

文章介绍 Qualcomm AI Hub提供了部署在云端边缘物理设备执行模型推理的任务&#xff0c;让你能够快速的评估在真实硬件上模型推理的精度和性能。本文介绍了如何使用AI Hub提供的接口在云端设备执行推理&#xff0c;更多详情可以参阅 Running Inference 模型推理 出于功耗和性能…

Rust Rocket简单入门

简介 Rust中最知名的两个web框架要数Rocket和Actix了&#xff0c;Rocket更注重易用性&#xff0c;Actix则更注重性能。这里只是了解一下Rust下的WebAPI开发流程&#xff0c;就学一下最简单的 Rocket。 Rocket 是一个用于 Rust 的异步 Web 框架&#xff0c;专注于可用性、安全性…

FreeRTOS教程9 软件定时器

目录 1、准备材料 2、学习目标 3、前提知识 3.1、软件定时器回调函数 3.2、软件定时器属性和状态 3.2.1、周期 3.2.2、分类 3.2.3、状态 3.3、软件定时器运行原理 3.3.1、RTOS 守护进程任务 3.3.2、定时器命令队列 3.3.3、守护进程任务调度 3.4、创建、启动软件定…

Web框架开发-Django模型层(数据库操作)

一、ORM介绍 MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动ORM是“对象-关系-映…

ubuntu20.04安装Pycharm

下载pycharm安装包 https://www.jetbrains.com/pycharm/download/#sectionlinux 使用社区版点击download 下载好的pycharm如图所示&#xff0c;右键解压&#xff1a; 打开终端&#xff0c;输入cd命令&#xff0c;进入刚刚解压文件夹下的bin文件夹&#xff0c;命令行是cd 文…

手撕算法-二叉搜索树与双向链表

牛客BM30。 描述&#xff1a;https://www.nowcoder.com/practice/947f6eb80d944a84850b0538bf0ec3a5?tpId295&tqId23253&ru/exam/oj&qru/ta/format-top101/question-ranking&sourceUrl%2Fexam%2Foj分析&#xff1a;二叉搜索树的中序遍历是递增序列。可以利用…

【AI工具】文字/图片生产3D模型-MVEdit 3D Toolbox

MVEdit 是一款无需培训的 3D 适配器,可 使用现成的 2D 稳定扩散模型进行 3D 生成/编辑 定位:一款功能强大的 3D 工具箱,可通过文本和图像创建和生成 3D 模型,具有可视化 UI 操作。 功能介绍: 能够从多视角图像生成高质量纹理网格,通过 3D 适配器实现出色的 3D 一致性。…

JAVA每日面经——并发编程(一)必看

&#x1f469;&#x1f3fd;‍&#x1f4bb;个人主页&#xff1a;阿木木AEcru &#x1f525; 系列专栏&#xff1a;《Docker容器化部署系列》 《Java每日面筋》 &#x1f4b9;每一次技术突破&#xff0c;都是对自我能力的挑战和超越。 目录 一、并发编程之AQS二、并发编程之CAS…

广东省30m二级分类土地利用数据(矢量)

广东省&#xff0c;地处中国大陆最南部&#xff0c;属于东亚季风区&#xff0c;从北向南分别为中亚热带、南亚热带和热带气候&#xff0c;是中国光、热和水资源最丰富的地区之一。主要河系为珠江的西江、东江、北江和三角洲水系以及韩江水系。广东省面积为17.977万平方公里&…

【python + Django】Django模板语法 + 请求和响应

前言&#xff1a; 现在现在&#xff0c;我们要开始将变量的值展现在页面上面啦&#xff01; 要是只会显示静态页面&#xff0c;我们的页面也太难看和死板了&#xff0c; 并且数据库的数据也没法展现在页面上。 但是呢&#xff0c;模板语法学习之后就可以啦&#xff01;&…

Halcon 3D 平面拟合(区域采样、Z值过滤、平面拟合、平面移动)

Halcon 3D 平面拟合(区域采样、Z值过滤、平面拟合、平面移动) 链接:https://pan.baidu.com/s/1UfFyZ6y-EFq9jy0T_DTJGA 提取码:ewdi * 1.读取图片 ****************

政安晨:【深度学习实践】【使用 TensorFlow 和 Keras 为结构化数据构建和训练神经网络】(二)—— 深度神经网络

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 概述 深度神经网络&#xff08;Deep Neural Network&…

24北京教资认定明日开始,请提前准备证件照

24北京教资认定明日开始&#xff0c;请提前准备证件照哦&#xff01;

KEY ENERGY欧洲意大利能源光伏储能展

3月1号第18届意大利里米尼国际可再生能源展&#xff08;KEY ENERGY&#xff09;由知名主办方ITALIAN EXHIBITION GROUP S.P.A组织举办&#xff0c;每年一届&#xff0c;是欧洲第二大能源展&#xff0c;也是覆盖范围最全知名度最高的可再生能源展览会。 该展会将于2024扩大规模…

EL表达式

一、什么是EL EL&#xff08;Expression Language&#xff09;表达式语言 由两个开发团队共同开发 JSP 标准标签库专家组 JSP 2.0 专家组 EL表达式语言的语法 ${Expression} JSP EL 表达式用于以下情形 在JSP页面中输出静态内容 为标准标签和自定义标签提供属性值 二、作用&am…

排序算法之选择排序介绍

目录 算法简介 算法描述 代码实现 算法简介 选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理&#xff1a;首先在未排序序列中找到最小&#xff08;大&#xff09;元素&#xff0c;存放到排序序列的起始位置&#xff0c;然后&#xff0c;再从剩余未排序元素…

解析服务器出现大量 TIME_WAIT 和 CLOSE_WAIT 状态的原因及排查方法

服务器出现大量 TIME_WAIT 状态的原因有哪些&#xff1f; 首先要知道 TIME_WAIT 状态是主动关闭连接方才会出现的状态&#xff08;别陷入一个误区不是只有客户端才能主动关闭连接的&#xff09;&#xff0c;所以如果服务器出现大量的 TIME_WAIT 状态的 TCP 连接&#xff0c;就是…

MongoDB系列之查询计划

概述 一个查询具体如何被执行的过程&#xff0c;称为查询计划。MongoDB采用自底向上的方式来构造查询计划&#xff0c;每一个查询计划&#xff08;query plan&#xff09;都会被分解为若干个有层次的阶段&#xff08;stage&#xff09;。整个查询计划最终会呈现出一颗多叉树。…

3个Tips,用“AI”开启新生活

相信最近&#xff0c;很多朋友们都回归到了忙碌的生活节奏中。生活模式的切换&#xff0c;或多或少会带来身体或情绪状况的起伏。新技术正在为人们生活的方方面面带来便利。3个小Tips或许能让你也从新技术中获益&#xff0c;从身到心&#xff0c;用“AI”开启新生活。 关”A…