跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

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

正确姿势是先用 fseek+ftell 获取文件大小并检查溢出,malloc 分配缓冲区,fseek 回起始位置,再以 fread(buf, 1, size, fp) 读取,并严格校验返回值是否等于 size。 用
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 ,强制转 unsigned char
避免符号扩展 后续要交给其他库(如 zlib、openssl)?确认它们是否要求内存对齐(如 16 字节),必要时用
posix_memalign
替代
malloc
真正麻烦的从来不是
fread
本身,而是你默认它“只是读”,却忘了它读出来的是裸字节——没有编码、没有边界、没有意图。每一步都要自己声明清楚:我要读多少、存在哪、怎么解释它。

相关文章