c++中如何实现文件的按块读取_c++处理超大文件读取方法【详解】
技术百科
裘德小鎮的故事
发布时间:2026-01-17
浏览: 次 不能直接用std::ifstream::read一次性读完超大文件,因内存不足会导致std::bad_alloc;即使分配成功,缓存失效和页交换也会使性能下降十倍以上。
为什么不能直接用 std::ifstream::read 一次性读完超大文件
因为内存不够。比如一个 20GB 的日志文件,new char[20ULL * 1024 * 1024 * 1024] 直接失败,std::bad_alloc 是最常见结果。更隐蔽的问题是:即使系统允许分配(如使用虚拟内存),后续处理时缓存失效、页交换会拖慢十倍以上——这不是 IO 瓶颈,是内存访问模式问题。
按块读取的核心不是“分多次调用 read”,而是控制每次真正加载进物理内存的数据量,并让 OS 缓存策略与你的访问顺序对齐。
用固定大小缓冲区 + read 循环是最稳的方案
不要依赖 gcount() 判断是否读到末尾——它只反映上一次 read 实际读入字节数,而 EOF 可能在任意位置发生。正确做法是检查 rdstate() 并结合 gcount()。
-
std::ifstream必须用std::ios::binary模式打开,否则 Windows 下遇到\r\n会被静默转换,块边界错乱 - 缓冲区大小建议设为 4KB–64KB(如
constexpr size_t BUF_SIZE = 8192;),太小导致 syscall 过多,太大无益于性能提升 - 每次
read(buf, BUF_SIZE)后立刻检查:if (file.gcount() == 0 && file.eof()) break;,避免空循环 - 处理最
后一块时,
gcount()返回值就是真实可用字节数,不要硬当成满缓冲区用
constexpr size_t BUF_SIZE = 32768;
std::ifstream file("huge.log", std::ios::binary);
if (!file) return;
char buffer[BUF_SIZE];
while (file.read(buffer, BUF_SIZE) || file.gcount() > 0) {
size_t n = static_cast(file.gcount());
process_chunk(buffer, n); // 自定义处理函数
if (file.eof()) break;
}
需要更高吞吐?试试 mmap(Linux/macOS)或 CreateFileMapping(Windows)
内存映射不是“把整个文件装进内存”,而是建立虚拟地址映射,按需触发 page fault 加载——这比手动 read/write 更贴近现代 SSD/NVMe 的并行读取能力。但代价是:你得自己管理映射范围、处理信号(如 SIGBUS)、且跨平台封装成本高。
- Linux 下用
mmap(nullptr, len, PROT_READ, MAP_PRIVATE, fd, offset),len不必等于文件大小,可分段映射 - Windows 需先
CreateFile得句柄,再CreateFileMapping+MapViewOfFile - 注意:映射区域不可写时,传
PROT_READ或PAGE_READONLY;若后续要修改,必须用MAP_SHARED和PAGE_READWRITE -
mmap失败返回MAP_FAILED(不是nullptr),别漏判
跳过某段内容?别用 seekg 频繁定位
对机械硬盘或某些网络文件系统,seekg 后紧跟 read 会产生大量寻道延迟。如果目标是“跳过前 100MB 解析后续”,更高效的做法是:用 read 循环丢弃数据,而不是反复 seek —— 因为连续读比随机 seek 快 3~10 倍。
- 丢弃数据时,复用同一栈缓冲区(如 8KB),避免堆分配开销
- 若需精确跳转到某行(如 CSV 第 100 万行),先用
read找换行符,而不是逐字节get() -
seekg在std::ios::binary模式下是字节偏移,安全;但在文本模式下行为未定义,禁用
超大文件处理真正的复杂点不在“怎么读”,而在“怎么定义‘一块’”:是固定字节数?按行?按 JSON 对象边界?这些语义解析逻辑一旦和底层读取耦合,就很难测试和复用。宁愿多一层抽象,把“块提取”和“块处理”拆开。
# ai
# 而不是
# 很难
# 加载
# 但在
# windows
# 跳过
# app
# 复用
# 设为
# mac
# linux
# js
# json
# 循环
# 对象
# macos
# 堆
# c++
# if
# 字节
# 模式下
# 栈
# 封装
# 虚拟内存
# char
# len
# break
# ios
# 硬盘
# csv
# 装进
# 句柄
# 机械硬盘
# EOF
# ifstream
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- php会话怎么开启_session_start函数
- Windows10系统更新错误0x80070002
- 如何使用Golang实现路由参数绑定_使用Mux和
- Windows服务持续崩溃怎样修复_系统服务保护机
- Win11怎么关闭开机声音_Win11系统启动提示
- 如何用列表一次性对 DataFrame 的指定列应
- Win10怎么卸载金山毒霸_Win10彻底卸载金山
- 如何在Golang中处理云原生事件_使用Event
- 电脑的“网络和共享中心”去哪了_Windows 1
- 如何使用Golang搭建本地API测试环境_快速验
- 使用类变量定义字符串常量时如何实现类型安全的 Li
- Python对象比较排序规则_集合使用说明【指导】
- C++如何使用Qt创建第一个GUI窗口?(入门教程
- 如何有效拦截拼接式恶意域名的垃圾信息
- Python正则表达式实战_模式匹配说明【教程】
- php查询数据怎么导出csv_查询结果转csv文件
- 如何使用Golang实现文件加密_Golang c
- php订单日志怎么按状态筛选_php筛选不同状态订
- 如何在Golang中捕获JSON序列化错误_Gol
- 如何在Golang中配置代码格式化工具_使用gof
- Win10怎样安装PPT模板_Win10安装PPT
- 如何在Golang中处理模块冲突_解决依赖版本不兼
- php中$this和::能混用吗_对象与静态作用域
- php485返回空数组怎么回事_php485数据接
- Linux如何挂载新硬盘_Linux磁盘分区格式化
- c++中如何对数组进行排序_c++数组排序算法汇总
- Win11如何设置环境变量 Win11添加和修改系
- php485在php5.6下能用吗_php485旧
- Drupal 中渲染节点时出现 HTML 标签嵌套
- php修改数据怎么改富文本_update更新htm
- 本地php环境出现502错误_nginx或apac
- Win11麦克风没声音怎么设置_Win11麦克风权
- Mac版Final Cut Pro入门_Mac视频
- Win11怎么查看硬盘型号_Windows 11检
- Go 中实现 Python urllib.quot
- php与c语言在嵌入式中有何区别_对比两者在硬件控
- Mac如何调整Dock栏大小和位置_Mac程序坞个
- Python网页解析流程_html结构说明【指导】
- c++中的std::conjunction和std
- Win11资源管理器卡顿怎么办 Win11文件资源
- Win10怎样安装Excel数据分析工具_Win1
- 网站内页做seo排名怎么做?
- Python大文件处理策略_内存优化说明【指导】
- 如何在Golang中使用container/hea
- Win11怎么关闭粘滞键_彻底禁用Windows
- windows如何修改文件默认打开方式_windo
- Win11怎么设置开机自动连接宽带_Windows
- C++中的constexpr和const有什么区别
- c++如何利用doxygen生成开发文档_c++
- Mac电脑如何恢复出厂设置_Mac抹掉数据并重装系


QQ客服