fread是最直接高效的分块读取方式,需用"rb"模式打开文件、检查返回值、配合vector管理4KB–64KB缓冲区;ifstream::read()次之,但须调clear()并用gcount()获取真实字节数。

用 fread 分块读取二进制大文件最直接
对纯二进制大文件(如日志、图像原始数据),fread 是最轻量、最可控的选择。它不带缓冲层,不解析换行,也不依赖流状态,适合精确控制每次读多少字节。
- 必须用
FILE*配合"rb"模式打开,否则 Windows 下可能因换行符转换导致块偏移错乱 - 每次调用
fread(buf, 1, size, fp)返回实际读取字节数,需严格检查是否等于预期值——读到末尾时必然小于预期,不能当作错误处理 - 缓冲区
buf建议用std::vector<char></char>管理,避免手动malloc/free;大小建议设为 4KB–64KB,太小增加系统调用开销,太大可能触发栈溢出或内存碎片
std::ifstream 的 read() 和 gcount() 配合使用
如果必须用 C++ 流接口(比如后续要混用 getline 或格式化读取),std::ifstream 的 read() 是唯一靠谱的分块方式,但要注意它不自动补零、不重置 eofbit。
- 务必在每次
read()前清掉failbit和eofbit:调用ifs.clear(),否则第二次读会直接失败 -
read()不保证填满缓冲区,结束后必须用ifs.gcount()获取真实读取字节数,不能依赖ifs.tellg()计算差值(中间有失败时不可靠) - 不要用
operator>>或getline()替代read()——它们内部有缓冲和跳过空白逻辑,块边界完全失控
遇到 mmap 时别盲目替换 fread
有人看到“大文件”就想到 mmap,但它不是万能加速器,尤其在机械硬盘或低内存机器上反而更慢。
-
mmap在 Linux 用mmap(),Windows 用CreateFileMapping()+MapViewOfFile(),跨平台成本高,且需要手动处理页面对齐和MAP_POPULATE等细节 - 随机访问密集场景才明显受益;顺序扫描大文件时,内核的 read-ahead 已经做得很好,
mmap只是把页缺失开销从read()调用转移到缺页中断,未必更快 - 32 位程序或内存紧张时,
mmap可能因地址空间不足直接失败,而fread只要缓冲区够小就能持续工作
文本大文件按行分块?先明确“块”定义
按“块”读文本文件本身是个模糊需求——是固定字节数?还是固定行数?还是按某种分隔符切?选错方案会导致逻辑断裂。
立即学习“C++免费学习笔记(深入)”;
- 若真要固定字节数分块(比如送进哈希函数),仍用
fread读原始字节,之后自己按\n拆行,注意最后一块可能无结尾换行符 - 若要固定行数分块(如每 1000 行一批处理),用
std::getline()循环计数即可,别试图用read()猜行边界——UTF-8 多字节字符、不同换行符(\r\n/\n)会让字节位置失效 - 用
std::fstream的seekg()跳转时,只对 ASCII 文本安全;含 UTF-8 或宽字符时,无法通过字节偏移精确定位行首
fread 最省心。真正麻烦的从来不是怎么读,而是怎么处理半截记录、怎么应对磁盘 I/O 中断、怎么让多线程读同一文件时不抢 offset——这些细节不会出现在“按块读取”的搜索结果里,但一跑真实数据就全冒出来。


















