c读取二进制文件到数组_fread批量读取并存储至缓冲区技巧

千静君_8135

千静君_8135

2026-03-23

824人浏览

原创

正确姿势是先用 fseek+ftell 获取文件大小并检查溢出,malloc 分配缓冲区,fseek 回起始位置,再以 fread(buf, 1, size, fp) 读取,并严格校验返回值是否等于 size。

c读取二进制文件到数组_fread批量读取并存储至缓冲区技巧

用 fread 一次性读完二进制文件到内存数组的正确姿势

直接调用 fread 读取整个文件到预分配数组是可行的,但必须先获取文件大小并确保缓冲区足够——否则轻则数据截断,重则越界写入。别信“读多少算多少”的侥幸心理。

  • 先用 fseek(fp, 0, SEEK_END) + ftell(fp) 获取真实字节长度,注意 ftell 返回 long,大文件需检查是否溢出(如 >2GB 时在某些平台可能出错)
  • 分配缓冲区用 malloc(file_size),别用栈数组(char buf[1024*1024]),栈空间太小且不可控
  • 调用前必须 fseek(fp, 0, SEEK_SET) 回到开头,否则从 EOF 开始读,fread 直接返回 0
  • fread(buf, 1, file_size, fp) 的第二个参数设为 1 最稳妥:它表示每个“元素”字节数,设成 1 才能保证返回值等于实际读取字节数;若设成 sizeof(int),返回值是“成功读取的元素个数”,容易误判

为什么 fread 返回值不等于文件大小?常见掉坑点

返回值小于预期,不一定是磁盘错误,大概率是操作逻辑或类型匹配问题。

  • 文件是以文本模式("rb" 没写对,写成 "r")打开的:Windows 下会把 \r\n 当作一个字符处理,导致 fread 实际读取字节数变少
  • 缓冲区指针为空或未初始化,fread 行为未定义,可能返回 0 也可能崩溃
  • 读取后没检查返回值:size_t n = fread(buf, 1, size, fp); if (n != size) { /* 缺失处理 */ } —— 这步跳过,后面所有基于“已全量读入”的假设都崩了
  • 多线程环境下共享 FILE* 且没加锁,fseek/fread 顺序可能被干扰

fread 批量读取 vs 循环小块读取:什么场景该选哪种?

不是所有情况都适合“一口吞”。内存受限、流式处理或校验需求强时,分块更稳。

  • 适合一次性读:配置文件、资源包、已知小而固定的二进制结构(如 PNG 头 8 字节、自定义协议头)
  • 适合循环读:网络响应体、日志文件、不确定大小的传感器数据流——每次读 4096 或 65536 字节,边读边解析或写入磁盘,避免 malloc 大内存失败
  • 注意:循环读时,fread 单次返回值可能小于请求长度(哪怕文件没结束),这是正常行为,不代表错误;只有返回 0 且 ferror(fp) 或 feof(fp) 为真才需终止

读取后数据怎么用?别直接当字符串处理

二进制数据不含 \0 终止符,用 printf("%s", buf) 或 strlen(buf) 会越界或截断——这是新手最常踩的隐性坑。

  • 需要按结构体解析?确保结构体打包对齐一致:#pragma pack(1) 或 __attribute__((packed)),否则 fread(&header, sizeof(header), 1, fp) 可能因内存布局差异读错字段
  • 要 hex dump 调试?用 for (int i = 0; i ,强制转 <code>unsigned char 避免符号扩展
  • 后续要交给其他库(如 zlib、openssl)?确认它们是否要求内存对齐(如 16 字节),必要时用 posix_memalign 替代 malloc

真正麻烦的从来不是 fread 本身,而是你默认它“只是读”,却忘了它读出来的是裸字节——没有编码、没有边界、没有意图。每一步都要自己声明清楚:我要读多少、存在哪、怎么解释它。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
printf用法大全
printf用法大全

php中文网为大家提供printf用法大全,以及其他printf函数的相关文章、相关下载资源以及各种相关课程,供大家免费下载体验。

2023.06.20

768

5

fprintf和printf的区别
fprintf和printf的区别

fprintf和printf的区别在于输出的目标不同,printf输出到标准输出流,而fprintf输出到指定的文件流。根据需要选择合适的函数来进行输出操作。更多关于fprintf和printf的相关文章详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.28

1009

10

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.03

1698

5

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.04

2604

5

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

2023.10.24

6024

49

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

2023.11.24

5509

6

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

2024.03.22

7194

16

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

2024.04.29

10354

11

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

2025.07.29

5279

17

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.7万人学习