在c++开发中,读取二进制文件是处理非文本类数据的常见需求,和读取文本文件不同,二进制文件读取需要以二进制模式打开文件,并且按照字节为单位读取数据,避免文本模式下的自动转义处理导致数据错误。

核心类和函数说明
c++读取二进制文件主要依赖fstream或者ifstream类,这两个类都属于标准库中的文件流操作类,其中ifstream是专门用于输入的文件流类,更适合只读场景。读取二进制文件的核心函数是read,它的作用是按照指定的字节数从文件中读取数据到内存缓冲区。
打开文件的模式
打开二进制文件时,必须在打开模式中添加ios::binary标志,否则文件会被当作文本模式处理,可能出现换行符转换、特殊字符截断等问题。常用的打开模式组合为ios::in | ios::binary,表示以输入和二进制模式打开文件。
基础读取示例
以下是一个读取二进制文件全部内容的简单示例,代码中会将文件读取到字符数组中,然后输出读取到的字节数:
#include <iostream>
#include <fstream>
#include <vector>
int main() {
// 定义要读取的二进制文件路径
const char* file_path = "test.bin";
// 创建ifstream对象,以二进制输入模式打开文件
std::ifstream in_file;
in_file.open(file_path, std::ios::in | std::ios::binary);
// 判断文件是否成功打开
if (!in_file.is_open()) {
std::cout << "文件打开失败" << std::endl;
return -1;
}
// 将文件指针移动到末尾,获取文件总大小
in_file.seekg(0, std::ios::end);
std::streamsize file_size = in_file.tellg();
// 将文件指针移回开头
in_file.seekg(0, std::ios::beg);
// 创建缓冲区存储读取的数据
std::vector<char> buffer(file_size);
// 读取全部文件内容,read函数第一个参数是缓冲区地址,第二个是读取字节数
in_file.read(buffer.data(), file_size);
// 检查是否读取成功
if (in_file.gcount() != file_size) {
std::cout << "文件读取不完整" << std::endl;
} else {
std::cout << "成功读取 " << file_size << " 字节数据" << std::endl;
}
// 关闭文件
in_file.close();
return 0;
}
读取自定义结构体二进制文件
实际开发中经常会遇到读取存储了自定义结构体数据的二进制文件,以下是读取存储了Person结构体数组的二进制文件示例:
#include <iostream>
#include <fstream>
#include <string>
// 定义自定义结构体,注意结构体最好不要包含指针成员,否则直接读取会出现问题
struct Person {
int id;
char name[20];
float score;
};
int main() {
std::ifstream in_file("person_data.bin", std::ios::in | std::ios::binary);
if (!in_file) {
std::cout << "文件打开失败" << std::endl;
return -1;
}
Person p;
// 循环读取结构体数据,直到文件结束
while (in_file.read(reinterpret_cast<char*>(&p), sizeof(Person))) {
std::cout << "ID: " << p.id << ", 姓名: " << p.name << ", 分数: " << p.score << std::endl;
}
in_file.close();
return 0;
}
注意事项
- 如果结构体中包含
string等动态分配内存的成员,不要直接读取整个结构体,因为string内部存储的是指针,直接读取会导致指针指向无效内存,应该分别读取每个成员。 - 不同平台可能存在字节序差异,比如小端序和大端序,跨平台读取二进制文件时需要先统一字节序再处理数据。
- 读取数据前一定要检查文件是否成功打开,读取后可以通过
gcount()函数获取实际读取的字节数,判断读取是否完整。 - 二进制文件读取完成后要及时关闭文件,释放系统资源。
常见问题解答
为什么读取二进制文件必须加ios::binary?
如果不加ios::binary,文件会以文本模式打开,在Windows系统中,文本模式会把换行符n自动转换为rn,读取时又会反向转换,这会导致二进制数据中的0x0A等字节被错误转换,最终读取的数据和原文件不一致。
读取的数据类型和文件中存储的不一致怎么办?
这种情况通常是因为写入和读取时的类型大小、对齐方式不一致导致的,建议写入和读取时使用相同的编译器、相同的结构体定义,必要时可以通过#pragma pack指定结构体的对齐方式,避免对齐填充导致的字节数差异。