fread一次性读取二进制文件最稳妥,需用"rb"模式、fseek+ftell(或fstat)获取大小、malloc分配后检查null、fread按字节读并校验返回值。

用 fread 一次性读取二进制文件到内存缓冲区
直接调用 fread 是最常用也最稳妥的方式,前提是已知文件大小且内存足够。它不解析内容、不换行处理、不跳过任何字节——纯按字节搬运。
- 必须先用
fseek+ftell获取文件长度(注意:对某些流如管道或标准输入不适用) - 分配缓冲区时用
malloc(size + 1)不必要,二进制数据不需要末尾\0;但若后续要当字符串用,得手动补零 -
fread(ptr, 1, size, fp)中第二个参数写成1最安全;写成size并设nmemb为1也行,但易和fwrite习惯混淆 - 务必检查返回值是否等于预期字节数:
if (read_count != size)—— 可能是磁盘错误、权限不足,或文件被其他进程截断
文件大小获取失败导致缓冲区分配错误
常见错误是没处理 ftell 返回 -1L,或者没用 fseek(fp, 0, SEEK_END) 成功就直接读长度。Windows 下打开文件没加 "rb" 模式,ftell 在文本模式下对二进制文件可能返回错误值。
- 打开文件必须用
fopen("file.bin", "rb"),"r"在 Windows 上会触发 CR-LF 转换,破坏长度判断 -
fseek(fp, 0, SEEK_END)失败时ftell不可信,应先检查fseek返回值是否为0 - 大文件(>2GB)在 32 位编译环境下,
long可能溢出,建议用fstat(POSIX)或_stat64(MSVC)替代
内存分配失败或越界访问的典型表现
程序崩溃在 fread 后的第一次数组访问,或者读出来全是乱码,大概率是 malloc 返回了 NULL 却没检查,还继续往里面写。
-
malloc失败返回NULL,必须显式判断:if (!buf) { perror("malloc"); return -1; } - 别用
sizeof(buf)获取缓冲区大小——那是指针大小(通常是 8),不是分配的字节数 - 释放前别重复
free(buf),也别对栈变量(比如char buf[4096])调用free - 如果文件空(size == 0),
malloc(0)行为由实现定义,有些返回NULL,有些返回有效地址,统一处理更稳
跨平台读取时的隐含陷阱
Linux 和 macOS 默认支持大文件(_FILE_OFFSET_BITS=64),但 Windows 的 MSVC 默认只认 32 位偏移,fseek/ftell 对 >4GB 文件会静默截断。
- Windows 下需定义
_CRT_SECURE_NO_WARNINGS和_USE_32BIT_TIME_T(禁用)并启用大文件支持 - 更可靠的做法是用
fstat(POSIX)或GetFileSizeEx(Windows API)代替fseek+ftell - 读取后不要假设字节序——如果数据含多字节整数,需按协议明确处理
ntohl/htons等转换
真正麻烦的从来不是读几行代码,而是文件大小拿不准、内存没判空、模式开错了这三件事。只要盯住这三个点,fread 就很老实。










