在 C 语言的文件操作体系中,fread 和 fwrite 是处理二进制文件的 “黄金搭档”。与处理文本文件的 fscanf、fprintf 不同,这两个函数能直接读写内存中的二进制数据,广泛应用于数据持久化、文件传输、硬件驱动开发等场景。本文将从基础原理到实战技巧,全面拆解 fread 与 fwrite 的使用方法,帮你避开常见坑点,写出高效、稳定的文件操作代码。
一、核心概念:为什么需要 fread /fwrite?
在了解具体用法前,我们先明确一个关键问题:为什么不直接用文本操作函数处理所有文件?
文本文件(如 .txt、.csv)的内容由可见字符组成,存储时会将数据转换为 ASCII 或 Unicode 编码(例如整数 123 会被拆分为 '1'、'2'、'3' 三个字符存储)。但二进制文件(如 .bin、.png、.exe)则直接存储内存中的原始字节(例如整数 123 在 32 位系统中会以 0x7B 0x00 0x00 0x00 四个字节存储)。
- 文本操作函数(fscanf/fprintf):适合人类可读的文本,需频繁进行 “数据 - 字符” 转换,效率低,且无法存储复杂结构(如结构体、数组)。
- 二进制操作函数(fread/fwrite):直接读写字节流,无需转换,效率高,可直接存储 / 读取内存中的变量、数组、结构体,是底层开发的首选。
二、函数原型与参数解析
fread 和 fwrite 均定义在 <stdio.h> 头文件中,二者参数结构完全一致,仅功能方向相反(读 vs 写)。
1. fwrite:将内存数据写入文件
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
参数详解:
| 参数名 |
类型 |
作用 |
| ptr |
const void* |
指向要写入文件的数据的内存地址(需强制转换为 void*,如 &data) |
| size |
size_t |
单个数据单元的字节数(例如 int 是 4,double 是 8,结构体用 sizeof 计算) |
| nmemb |
size_t |
要写入的数据单元个数(例如写入 10 个 int,则 nmemb=10) |
| stream |
FILE* |
文件指针(由 fopen 打开,且模式需包含 w(写)、a(追加)或 r+(读写)) |
返回值:
- 成功:返回实际写入的 “数据单元个数”(理想情况下等于 nmemb)。
- 失败 / 到达文件尾:返回值小于 nmemb(需通过 ferror 或 feof 判断具体原因)。
2. fread:从文件读取数据到内存
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
参数详解:
| 参数名 |
类型 |
作用 |
| ptr |
void* |
指向接收数据的内存缓冲区(需提前分配空间,如数组、结构体变量地址) |
| size |
size_t |
单个数据单元的字节数(与写入时的 size 必须一致,否则数据错乱) |
| nmemb |
size_t |
要读取的数据单元个数 |
| stream |
FILE* |
文件指针(打开模式需包含 r(读)或 r+(读写)) |
返回值:
- 成功:返回实际读取的 “数据单元个数”(等于 nmemb 表示读取完整)。
- 失败 / 到达文件尾:返回值小于 nmemb(需通过 ferror 或 feof 判断)。
三、实战场景:从基础到进阶
掌握参数后,我们通过 4 个典型场景,逐步深入 fread/fwrite 的使用技巧。
场景 1:写入 / 读取单个基本数据类型(如 int、float)
需求:将一个整数 1024 写入二进制文件,再读取回来并打印。


1万+

被折叠的 条评论
为什么被折叠?



