C++使用read()和write()读写二进制文件的详细指南

Ada
Ada
发布时间:2026-10-15| 5人浏览过
原创

在使用C++进行数据存储时,二进制读写因其固定长度和高效率,在处理结构体或类对象(如学籍信息)时优于文本模式。本文将重点讲解如何利用`std::fstream`库提供的`read()`和`write()`成员函数,实现基于二进制的文件输入输出操作,确保数据紧凑存储与高效读取。

二进制读写的必要性与原理

在处理包含固定格式数据的程序(例如学生信息管理)时,使用重载的 `>>` 和 `<<` 运算符进行文本形式读写虽然直观,但存在占用空间大、不利于快速查找等缺点。以二进制形式直接写入内存对象,可确保每条记录占用固定的字节数(即 `sizeof(ClassName)`),从而显著提升存储密度和处理效率。

对于二进制读写,C++ 标准库提供了专门的非格式化 I/O 成员函数:write() 用于将内存缓冲区的数据写入文件流,read() 则用于从文件流读取指定字节数到内存缓冲区。

准备条件:定义数据结构与头文件

在进行二进制读写前,需要定义待处理的数据结构。注意,在二进制模式下,字符数组的大小应当足够容纳预期数据,且需留意平台间的结构体对齐差异。

class CStudent
{
public:
    char szName[20];  // 姓名,预留足够空间
    int age;          // 年龄
};

同时,必须包含 `` 和 `` 头文件,并使用 `std` 命名空间。

第1步:使用write()写入二进制文件

目的:将内存中的 `CStudent` 对象序列化为二进制数据并保存到磁盘文件。

入口:使用 `ofstream` 或 `fstream` 对象。

动作说明:调用 `write(const char* s, streamsize n)` 方法。参数 `s` 为指向要写入数据的起始地址,通常需要对类对象地址进行强制类型转换 `(char*)&s`;参数 `n` 为写入的字节数,通常设为 `sizeof(s)`。

重要参数:打开文件时必须指定 `ios::binary` 标志,特别是在 Windows 平台下,否则换行符等控制字符可能被转义,导致二进制数据损坏。

#include <iostream>
#include <fstream>
using namespace std;

class CStudent
{
public:
    char szName[20];
    int age;
};

int main()
{
    CStudent s;
    // 以二进制写模式打开文件
    ofstream outFile("students.dat", ios::out | ios::binary);
    
    // 模拟从控制台输入学生信息
    while (cin >> s.szName >> s.age)
    {
        // 将对象的内存数据写入文件
        outFile.write((char*)&s, sizeof(s));
    }
    
    outFile.close(); // 关闭文件确保数据完整保存
    return 0;
}

执行上述程序后,生成的 `.dat` 文件将无法通过普通文本编辑器正常阅读,因为其内容为原始的二进制字节流。每个学生的记录在文件中占据固定的 `sizeof(CStudent)` 字节。

第2步:使用read()读取二进制文件

目的:按照写入时的顺序,从二进制文件中恢复数据到内存对象中。

入口:使用 `ifstream` 或 `fstream` 对象。

动作说明:调用 `read(char* s, streamsize n)` 方法。该函数尝试从文件流中读取 `n` 个字节放入指针 `s` 指向的缓冲区中。如果读取成功,返回流对象本身,可作为循环判断条件;若到达文件末尾或发生错误,流状态变为假,循环终止。

完成状态判断:可以通过检查流的状态或使用 `gcount()` 方法获取最后一次实际读取的字节数。

#include <iostream>
#include <fstream>
using namespace std;

class CStudent
{
public:
    char szName[20];
    int age;
};

int main()
{
    CStudent s;       
    // 以二进制读模式打开文件
    ifstream inFile("students.dat", ios::in | ios::binary); 
    
    if(!inFile) {
        cout << "Open file error!" << endl;
        return 0;
    }
    
    // 连续读取直到文件结束
    while(inFile.read((char *)&s, sizeof(s))) { 
        cout << s.szName << " " << s.age << endl;   
    }
    
    inFile.close();
    return 0;
}

此段代码会逐条还原之前写入的学生信息。需要注意的是,`read()` 方法依赖于文件内部的读指针,每读取若干字节,指针自动向后移动,因此无需手动指定偏移量即可顺序读取整个文件。

关键注意事项与排错

  • 权限与路径:确保目标目录有写入权限,且在Windows系统中务必加 `ios::binary`,防止因编码转换导致的文件内容不可逆破坏。
  • 数据类型一致性:读写双方的类结构定义必须完全一致(包括字段顺序和数据类型)。若一方增加了新字段而另一方未同步,读取时将错位匹配剩余数据。
  • 内存对齐:不同编译器或架构可能导致结构体内存对齐方式不同,跨平台传递此类二进制文件时需特别注意打包布局。

总结

通过使用 `write()` 和 `read()`,开发者可以绕过文本格式的解析开销,直接在内存与硬盘之间传输结构化的二进制数据。这种方式在处理大型日志、游戏存档或数据库缓存文件时极为常见且高效。以上就是C++使用read()和write()读写二进制文件的详细内容,更多关于C++文件流操作的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。