【C 语言】文件操作 ( fread 函数 )

article/2025/11/11 2:44:04

文章目录

  • 一、fread 函数
  • 二、缓冲区受限的情况 ( 循环读取文件 | feof 函数判定文件读取完毕 )
  • 三、处理乱码问题
  • 四、记录读取的字节个数
  • 五、读取到 0 字节的情况
  • 六、读取完毕的情况
  • 七、读取文本文件 " " 与 读取二进制文件 " " 区别

二进制文件读写两个重要的函数 , fread 和 fwrite , fread 用于读取文件 , fwrite 用于写出文件 ;

fread / fwrite 函数 既可以操作 二进制文件 , 又可以操作 文本文件 ;

getc / putc 函数 , fscanf / fprintf 函数 , fgets / fgets 函数 , 只能用于操作 文本文件 ;

一、fread 函数


fread 函数作用 : 从文件中读取若干字节数据到内存缓冲区中 ;

fread 函数原型 :

size_t fread( void *buffer, size_t size, size_t count, FILE *stream );

void *buffer 参数 : 将文件中的二进制数据读取到该缓冲区中 ;

size_t size 参数 : 读取的 基本单元 字节大小 , 单位是字节 , 一般是 buffer 缓冲的单位大小 ;

  • 如果 buffer 缓冲区是 char 数组 , 则该参数的值是 sizeof(char) ;
  • 如果 buffer 缓冲区是 int 数组 , 则该参数的值是 sizeof(int) ;

size_t count 参数 : 读取的 基本单元 个数 ;

FILE *stream 参数 : 文件指针 ;

size_t 返回值 : 实际从文件中读取的 基本单元 个数 ; 读取的字节数是 基本单元数 * 基本单元字节大小 ;

代码示例 : 一次性读满整个缓冲区 ;

#include <stdio.h>int main()
{// 使用 "rb" 读取二进制方式打开文件FILE *p = fopen("D:\a.txt", "rb");// 用于接收读取数据的缓冲区char buffer[1024] = {0};// buffer : 将文件读取到内存的位置// sizeof(char) : 读取的基本单元字节长度// sizeof(buffer) : 读取的基本单元个数,//       读取字节个数是 sizeof(buffer) * sizeof(char)// p : 文件指针fread(buffer, sizeof(char), sizeof(buffer), p);// 打印读取的内容printf("buffer = %s
", buffer);printf("Main End
");return 0;
}

执行结果 :

在这里插入图片描述

二、缓冲区受限的情况 ( 循环读取文件 | feof 函数判定文件读取完毕 )


假设缓冲区很小 , 文件很大 , 则需要循环读取文件数据 ;

使用 feof(p) 判定文件是否读取完毕 , 如果返回 true 说明文件没有读取完毕 , 返回 false , 说明文件读取完毕 ;

代码示例 :

#include <stdio.h>int main()
{// 使用 "rb" 读取二进制方式打开文件FILE *p = fopen("D:\a.txt", "rb");// 用于接收读取数据的缓冲区char buffer[4] = {0};while(!feof(p)){memset(buffer, 0, sizeof(buffer));// buffer : 将文件读取到内存的位置// sizeof(char) : 读取的基本单元字节长度// sizeof(buffer) : 读取的基本单元个数,//       读取字节个数是 sizeof(buffer) * sizeof(char)// p : 文件指针fread(buffer, sizeof(char), sizeof(buffer), p);// 打印读取的内容printf("buffer = %s
", buffer);}printf("Main End
");return 0;
}

执行结果 : 读取之后出现乱码 , 这是由于每次读取 10 10 10 字节 , 但是字符串必须要以 ‘’ 进行结尾 , 如果没有 ‘’ 则会一直读取直到出现 ‘’ 字符串结尾位置 ;

在这里插入图片描述

三、处理乱码问题


为了避免上述打印出现乱码的情况 , char buffer[4] = {0}; 准备了 4 4 4 字节缓冲区 , 每次只使用其中的 3 3 3 个字节 , 这就能保证最后一个字节必定是 ‘’ , 打印时就不会出现乱码 ;

代码示例 :

#include <stdio.h>int main()
{// 使用 "rb" 读取二进制方式打开文件FILE *p = fopen("D:\a.txt", "rb");// 用于接收读取数据的缓冲区char buffer[4] = {0};while(!feof(p)){memset(buffer, 0, sizeof(buffer));// buffer : 将文件读取到内存的位置// sizeof(char) : 读取的基本单元字节长度// sizeof(buffer) : 读取的基本单元个数,//       读取字节个数是 sizeof(buffer) * sizeof(char)// p : 文件指针fread(buffer, sizeof(char), sizeof(buffer) - 1, p);// 打印读取的内容printf("buffer = %s
", buffer);}printf("Main End
");return 0;
}

执行结果 : 每次从文件中读取 缓冲区字节数 - 1 个字节 , 则能完整的将文本打印出来 ;

在这里插入图片描述

四、记录读取的字节个数


fread 函数返回值表示读取到的 基本单元 的个数 , 如果设置了 1KB 的缓冲区 , 但是文件中只有 5 字节 , 则 fread 的返回值就是实际读取到的数据个数 ;

代码示例 :

#include <stdio.h>int main()
{// 使用 "rb" 读取二进制方式打开文件FILE *p = fopen("D:\a.txt", "rb");// 用于接收读取数据的缓冲区char buffer[1024] = {0};// buffer : 将文件读取到内存的位置// sizeof(char) : 读取的基本单元字节长度// sizeof(buffer) : 读取的基本单元个数,//       读取字节个数是 sizeof(buffer) * sizeof(char)// p : 文件指针// 返回值 : fread 函数返回值表示读取到的 基本单元 的个数size_t count = fread(buffer, sizeof(char), sizeof(buffer) - 1, p);// 打印读取的内容printf("buffer = %s , read count = %u
", buffer, count);printf("Main End
");return 0;
}

执行结果 :

在这里插入图片描述

五、读取到 0 字节的情况


如果 基本单元 大小 4 4 4 字节 , 文件中只有 3 3 3 字节数据 , 则使用 fread 函数读取文件 , 缓冲区设置 1KB , 则实际读取到的基本单元个数是 0 0 0 ;

代码示例 :

#include <stdio.h>int main()
{// 使用 "rb" 读取二进制方式打开文件FILE *p = fopen("D:\a.txt", "rb");// 用于接收读取数据的缓冲区char buffer[1024] = {0};// buffer : 将文件读取到内存的位置// sizeof(char) : 读取的基本单元字节长度// sizeof(buffer) : 读取的基本单元个数,//       读取字节个数是 sizeof(buffer) * sizeof(char)// p : 文件指针// 返回值 : fread 函数返回值表示读取到的 基本单元 的个数size_t count = fread(buffer, sizeof(int), sizeof(buffer) - 1, p);// 打印读取的内容printf("buffer = %s , read count = %u
", buffer, count);printf("Main End
");return 0;
}

执行结果 :

在这里插入图片描述

六、读取完毕的情况


如果文件已经读取完毕 , 不关闭文件 , 再次调用 fread 函数继续读取 , 则读取到的 基本单元 个数是 0 0 0 ;

使用 feof(p) 判定文件是否读取完毕 , 如果返回 true 说明文件没有读取完毕 , 返回 false , 说明文件读取完毕 ;

代码示例 :

#include <stdio.h>int main()
{// 使用 "rb" 读取二进制方式打开文件FILE *p = fopen("D:\a.txt", "rb");// 用于接收读取数据的缓冲区char buffer[1024] = {0};// buffer : 将文件读取到内存的位置// sizeof(char) : 读取的基本单元字节长度// sizeof(buffer) : 读取的基本单元个数,//       读取字节个数是 sizeof(buffer) * sizeof(char)// p : 文件指针// 返回值 : fread 函数返回值表示读取到的 基本单元 的个数size_t count = fread(buffer, sizeof(char), sizeof(buffer) - 1, p);// 打印第一次读取的内容printf("First fread : buffer = %s , read count = %u
", buffer, count);count = fread(buffer, sizeof(int), sizeof(buffer) - 1, p);// 打印第二次读取的内容printf("Second fread : buffer = %s , read count = %u
", buffer, count);printf("Main End
");return 0;
}

执行结果 :

在这里插入图片描述

七、读取文本文件 “ ” 与 读取二进制文件 “ ” 区别


以下区别只在 Windows 系统存在 , 在 Linux / Unix 中读取文本数据与二进制数据没有区别 ;

使用 ‘rb’ 方式打开文件 , 读取二进制文件 , 然后调用 fread 函数读取文件 ,

#include <stdio.h>int main()
{// 使用 "rb" 读取二进制方式打开文件FILE *p = fopen("D:\a.txt", "rb");// 用于接收读取数据的缓冲区char buffer[1024] = {0};// buffer : 将文件读取到内存的位置// sizeof(char) : 读取的基本单元字节长度// sizeof(buffer) : 读取的基本单元个数,//       读取字节个数是 sizeof(buffer) * sizeof(char)// p : 文件指针// 返回值 : fread 函数返回值表示读取到的 基本单元 的个数size_t count = fread(buffer, sizeof(char), sizeof(buffer) - 1, p);// 打印第一次读取的内容printf("fread : buffer = %s , read count = %u
", buffer, count);// 逐个字节打印读取出数据的 ASCII 码int i = 0;for(i = 0; i < count; i ++){printf("buffer[%d] = %x
", i, buffer[i]);}printf("Main End
");return 0;
}

执行结果 : 第 2 2 2 个索引读取出来的值是 0xd 对应 ‘ ’ , 第 3 3 3 个值是 0xa 对应 ‘ ’ ;

注意 : 最后两个字节是空行对应的 “ ” ;

fread : buffer = ab
cd, read count = 8
buffer[0] = 61
buffer[1] = 62
buffer[2] = d
buffer[3] = a
buffer[4] = 63
buffer[5] = 64
buffer[6] = d
buffer[7] = a
Main End

在这里插入图片描述

使用 ‘r’ 方式打开文件 , 读取文本文件 , 然后调用 fread 函数读取文件 ,

#include <stdio.h>int main()
{// 使用 "rb" 读取二进制方式打开文件FILE *p = fopen("D:\a.txt", "r");// 用于接收读取数据的缓冲区char buffer[1024] = {0};// buffer : 将文件读取到内存的位置// sizeof(char) : 读取的基本单元字节长度// sizeof(buffer) : 读取的基本单元个数,//       读取字节个数是 sizeof(buffer) * sizeof(char)// p : 文件指针// 返回值 : fread 函数返回值表示读取到的 基本单元 的个数size_t count = fread(buffer, sizeof(char), sizeof(buffer) - 1, p);// 打印第一次读取的内容printf("fread : buffer = %s , read count = %u
", buffer, count);// 逐个字节打印读取出数据的 ASCII 码int i = 0;for(i = 0; i < count; i ++){printf("buffer[%d] = %x
", i, buffer[i]);}printf("Main End
");return 0;
}

执行结果 : 第 2 2 2 个索引读取出来的值是 0xa 对应 ‘ ’ ;

最后的空行只有一个 ‘ ’ ;

fread : buffer = ab
cd, read count = 6
buffer[0] = 61
buffer[1] = 62
buffer[2] = a
buffer[3] = 63
buffer[4] = 64
buffer[5] = a
Main End

在这里插入图片描述


http://chatgpt.dhexx.cn/article/MjDokAGH.shtml

相关文章

Scala对象 转Json字符串

2019独角兽企业重金招聘Python工程师标准>>> import org.json4s.{Formats, NoTypeHints} import org.json4s.jackson.Serialization import org.json4s.jackson.Serialization.writeobject Json4sDemo {// 需要添加隐式转换implicit val formats: AnyRef with Forma…

【系统学习SpringBoot】SpringBoot 对象转JSON输出

SpringBoot输出JSON 以往使用SpringMVC中开发时&#xff0c;对象转JSON需要配置很多东西 【1】添加FastJson/jackjson等第三方jar 【2】在配置文件中配置Controller扫描 【3】给方法添加ResponseBody 配置FastJson还需要给配置文件中添加(很麻烦( ▼-▼ )) <mvc:annot…

【Java 笔记】使用Fastjson2时,对象转json首字母大小写问题

开发环境&#xff1a; Spring cloud Fastjson2 一、JSON 转 Object 推送第三方数据时&#xff0c;对方http接口消息体为json&#xff0c;但是字段首字母大写 我们需要接收JSON 转 Object [ { "ItemCode": "WIND_SPEED", "ItemValue": "2.1…

js 数组、对象转json 以及json转 数组、对象

1、JS对象转JSON 方式&#xff1a;JSON.stringify(obj) var json {"name":"iphone","price":666}; //创建对象&#xff1b; var jsonStr JSON.stringify(json); //转为JSON字符串 console.log(jsonStr);2、JS数组转JSON //数组转json…

对象转JSON首字母大写

最近在做一个第三方接口&#xff0c;接口给的数据类型如下 请求报文如下 {"A0144":"12141256","AB6AM":"中国银行支行","STATUS":1} 一般按照对象转JSON会使首字母小写&#xff0c;与接口文档不相符&#xff0c;因此需要…

Object对象转实体对象,java对象转json

Object对象转实体对象 在后台发起HTTP请求的时候&#xff0c;响应体传回的一般是Object或者JSON字符串。 方法一 要将Object对象转换成实体类对象可以先使用com.alibaba.fastjson.JSONObject类的toJSONString方法将Object对象转换成JSON字符串&#xff0c;然后再调用JSONObj…

对象 和 json 互转 四种方式 json-lib、Gson、FastJson、Jackson

文章目录 一、 json-lib二、 Google的Gson1.简介2. 配置步骤1. MAVEN 依赖引入2. gsonUtil 工具类3. 排除不要序列化的熟悉注解类 Exclude 三. 阿里巴巴的FastJson1.简介2.配置步骤1.引入maven2. 配置 CustomFastjsonConfig3. 测试 4. 开源的Jackson简介&#xff1a;Jackson配置…

大数据Java学哪个好,哪个更有发展前景?

文章来源&#xff1a;加米谷大数据 在IT职业技能培训当中&#xff0c;Java开发可以说是非常经典的一个方向&#xff0c;行业当中对于Java开发人才&#xff0c;早年可以是存在长期持续性的需求。而大数据&#xff0c;作为近年来的新兴技术热点&#xff0c;也同样备受关注。因此很…

大数据Java基础之常用类

欢迎关注公众号&#xff1a; 9-1 字符串相关的类 String常用方法 9-2 JDK8之前日期时间API 9-4 Java比较器 9-5 System类 9-6 Math类 9-7 BigInteger与BigDecimal

Java毕设项目医疗大数据系统计算机(附源码+系统+数据库+LW)

Java毕设项目医疗大数据系统计算机&#xff08;附源码系统数据库LW&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项…

方向选择(嵌入式 大数据 java)

时间匆匆&#xff0c;不知不觉大二后半期了。晚上开了会要确定方向选择&#xff0c;嵌入式&#xff0c;大数据&#xff0c;java三个方向。 犹豫了好久&#xff0c;因为学了一段时间的java还是偏向于java的 不过也想学大数据&#xff0c;因为最近很火 大家都 知道的。现在来简…

大数据入门:Java和Scala编程对比

在学习大数据之初&#xff0c;很多人都会对编程语言的学习有疑问&#xff0c;比如说大数据编程主要用什么语言&#xff0c;在实际运用当中&#xff0c;大数据主流编程是Java&#xff0c;但是涉及到Spark、Kafka框架&#xff0c;还需要懂Scala。今天的大数据入门分享&#xff0c…

视频教程-大数据Java强化班(十)之大数据爬虫-Java

大数据Java强化班(十)之大数据爬虫 10年一线开发及项目管理经验&#xff0c;6年以上大数据项目架构、实施、开发与运维经验&#xff0c;骨灰级大数据玩家&#xff0c;对Hadoop、Storm、Spark、Flink、Kylin、Druid等大数据技术有较深研究。搭建、维护过上百节点集群&#xff0c…

Java大数据开发

(后记&#xff1a;写这些东西不管出于什么目的&#xff0c;总之自己乐意&#xff0c;有时候回顾一下&#xff0c;别有一番滋味&#xff01;) 博主 QQ&#xff1a;1103088881 idea 从菜鸟到大神 css-3d旋转相册 时钟罗盘 Java学习方法总结 Java 面向对象 …

大数据用Python还是JAVA

前言 大数据用python还是java?书声琅琅教育番茄老师介绍&#xff0c;人生苦短&#xff0c;我用python&#xff0c;这是目前比较流行的行话了&#xff0c;对于用python好还是JAVA好&#xff0c;大家都有自己的看法&#xff0c;虽然JAVA流行时间较&#xff0c;但是python出现的…

Java及大数据学习路线

1.Java学习路线 1.1JavaSE Java基础 Java8新特性 数据库MySQL与SQL语言 JDBC 1.2JavaWeb HTML基础与CSS JavaScript DOM 与 jQuery XML与Tomcat HTTP协议 服务器端组件Servlet JSP EL表达式 JSTL 会话控制Cookie和Session 服务器端组件Filter 服务器端组件Listener 国际化 …

搞大数据,Java 工程师需要掌握哪些知识?

先看再点赞&#xff0c;给自己一点思考的时间&#xff0c;微信搜索【沉默王二】关注这个有颜值却假装靠才华苟且的程序员。 本文 GitHub github.com/itwanger 已收录&#xff0c;里面还有我精心为你准备的一线大厂面试题。 题目是一名叫“截然不同”的同学私信我的一个问题&…

大数据Java基础之Java反射机制

欢迎关注公众号&#xff0c;一起进步&#xff0c;共同成长。 15-1 Java反射机制概述 15-2 理解Class类并 获取Class的实例 15-3 类的加载 与ClassLoader的理解 15-4 创建运行时类的对象 15-5 获取运行时类的完 整结构 15-6 调用运行时类的指定结构 15-7 反射的应用&#xff1a;…

大数据java基础吗?

大数据必备 关于大数据基础知识&#xff0c;以前浪尖写过一篇文章&#xff0c;也多次在 知识星球里分享过经验。 具体学习内容&#xff0c;可以参看如下文章&#xff1a; 入门大数据必读 这个可以看到做大数据的话java是必需品&#xff0c;因为基本所有的大数据框架都是jvm开发…