C++用ifstream读取二进制文件详细步骤+代码

12次阅读

用 std::ifstream 二进制读文件必须加 std::ios::binary,否则 windows 下会错误转换 rn;需检查 is_open()、用 seekg/tellg 获取大小、read() 后必查 gcount()、close() 后检查 fail()。

C++用ifstream读取二进制文件详细步骤+代码

std::ifstream 以二进制模式打开文件必须加 std::ios::binary

不加这个标志,windows 下会把 rn 自动转成 n,读出来的字节数和文件实际大小对不上,尤其读图片、音频、加密数据时直接出错。linux/macOS 虽然影响小,但跨平台代码必须统一加

常见错误:只写 std::ifstream file("data.bin") —— 这是文本模式,默认启用换行符转换。

  • 正确写法:std::ifstream file("data.bin", std::ios::binary)
  • 打开后务必检查:if (!file.is_open()) { /* 处理失败 */ }
  • 如果路径含中文或特殊字符,c++ 标准库在 Windows 上默认不支持宽字符路径,建议用 UTF-8 编码路径 + 编译器扩展(如 MSVC 的 /utf-8)或改用 std::Filesystem::u8path(C++17)

读取全部内容到内存推荐用 std::vector + read

std::ifstream::read() 是最可控的二进制读取方式,它不解析内容、不跳过空白、不添加终止符,完全按字节搬运。配合 std::vector 可避免手动 new[]/delete[] 和缓冲区溢出风险。

别用 getline()>> 操作符——它们是为文本设计的,遇到 或控制字符就停了。

立即学习C++免费学习笔记(深入)”;

std::ifstream file("data.bin", std::ios::binary); if (!file.is_open()) {     // 错误处理 } file.seekg(0, std::ios::end); size_t size = file.tellg(); file.seekg(0, std::ios::beg); 

std::vector buffer(size); file.read(buffer.data(), size);

// 检查是否读满 if (file.gcount() != static_cast(size)) { // 读取异常:磁盘错误、权限不足、文件被截断等 }

gcount() 是唯一可靠的方式判断实际读了多少字节

read() 不抛异常(除非设置了 exceptions()),也不返回成功字节数。它只更新内部状态,而 gcount() 返回上一次输入操作实际提取的字符数——这是你唯一能信的数字。

  • 即使 file.good() 为 true,gcount() 也可能小于预期(比如文件末尾突然变小)
  • 不要依赖 file.EOF() 判断读完:它只在尝试读越界后才置位,容易误判
  • 如果要分块读大文件(比如 64KB 一块),每次调用 read() 后都得立刻查 gcount()

关闭文件前记得检查 failbit 防止静默失败

二进制读取中,磁盘 I/O 错误可能不立即暴露。比如读到一半电源中断,read() 可能只返回部分字节,failbit 却没立刻置位;直到你调用 close() 或析构时才触发底层错误。

所以,在 file.close() 后应检查状态:

file.close(); if (file.fail()) {     // 底层 close 失败:磁盘已满、文件系统只读、权限变更等     // 此时 buffer 中的数据仍是有效的(读取已完成),但需记录该错误 }

更稳妥的做法是:读完即用 file.exceptions(std::ios::failbit | std::ios::badbit) 开启异常,让错误在发生时立刻抛出——但要注意,这会让 close() 也抛异常,需包裹 try/catch

实际项目里最容易被忽略的是:没验证 gcount(),也没检查 close() 结果,导致“以为读全了”,结果后续解析崩溃。

text=ZqhQzanResources