【STL】iostream 编程:二进制输出文件


本文介绍一下二进制输出文件的规则及其作用。


目录

  • [1 概述](#1 概述)
  • [2 二进制输出](#2 二进制输出)
  • [3 示例](#3 示例)
  • [4 说明](#4 说明)

1 概述

流最初是为文本处理设计的,因此文件输出默认采用文本模式在文本模式下,写入时单个换行符 \n 会自动扩展为 Windows 系统的回车 + 换行双字符 \r\n。这种自动转换会破坏二进制数据,示例如下:

cpp 复制代码
// binary_output_files.cpp
// compile with: /EHsc
#include <fstream>
using namespace std;
int iarray[2] = { 99, 10 };
int main( )
{
    ofstream os( "test.dat" );
    os.write( (char *) iarray, sizeof( iarray ) );
}

开发者预期输出字节序列:{99,0,10,0};

但文本模式下实际写入:{99,0,13,10,0},多插入了回车符 \r,后续读取二进制数据的程序会解析出错。

2 二进制输出

如果需要纯粹的二进制输出、字节原样写入不做任何字符转换,构造 ofstream 时传入 ios_base::binary 打开模式标志:

cpp 复制代码
// binary_output_files2.cpp
// 编译参数:/EHsc
#include <fstream>
using namespace std;
int iarray[2] = { 99, 10 };

int main()
{
   ofstream ofs ( "test.dat", ios_base::binary );
   // 精确写入8个字节,无任何字符转译
   ofs.write( (char*)&iarray[0], sizeof(int)*2 );
}

3 示例

下述示例分别通过文本模式和二进制模式写入,然后二进制模式读取查看区别,文本模式读取查看区别:

cpp 复制代码
// binary_output_files.cpp
// 编译参数:/EHsc
#include <fstream>
#include <iostream>
using namespace std;

int iarray[2] = { 99, 10 };

int main()
{
    //文本模式写入(无ios::binary)
    {
        ofstream os("test.dat");
        os.write((char*)iarray, sizeof(iarray));
        os.close();

        //二进制读取
        ifstream is("test.dat", ios::binary);
        char buf[16] = { 0 };
        is.read(buf, sizeof(buf));
        is.close();

        //逐字节打印十六进制,观察多出0x0D(13)
        cout << "文件内字节(十六进制):" << endl;
        for (int i = 0; i < sizeof(iarray) + 2; i++)
        {
            printf("%02X ", (unsigned char)buf[i]);
        }
        cout << endl;

        //文本模式读取
        int readArr[2] = { 0 };
        ifstream textIn("test.dat");
        textIn.read((char*)readArr, sizeof(readArr));
        textIn.close();

        cout << "预期数组:[99, 10]" << endl;
        cout << "文本模式读回:[" << readArr[0] << ", " << readArr[1] << "]" << endl;
    }

    //二进制模式写入(ios::binary)
    {
        ofstream os("test2.dat", ios::binary);
        os.write((char*)iarray, sizeof(iarray));
        os.close();

        //二进制读取
        ifstream is("test2.dat", ios::binary);
        char buf[16] = { 0 };
        is.read(buf, sizeof(buf));
        is.close();

        //逐字节打印十六进制,观察多出0x0D(13)
        cout << "文件内字节(十六进制):" << endl;
        for (int i = 0; i < sizeof(iarray) + 2; i++)
        {
            printf("%02X ", (unsigned char)buf[i]);
        }
        cout << endl;

        //文本模式读取
        int readArr[2] = { 0 };
        ifstream textIn("test2.dat");
        textIn.read((char*)readArr, sizeof(readArr));
        textIn.close();

        cout << "预期数组:[99, 10]" << endl;
        cout << "文本模式读回:[" << readArr[0] << ", " << readArr[1] << "]" << endl;
    }

    return 0;
}

运行结果:

很明显,二进制读取的时候是有问题的,但是文本模式写入二进制模式读取本身逻辑上就不通畅,所以什么方式写入什么方式读取不就好了。

4 说明

  1. 文本模式转换规则(仅 Windows 平台生效)
    • 写入:内存中的 \n (0x0A)自动变成 \r\n (0x0D 0x0A)存入文件;
    • 读取:文件里连续的 \r\n 自动还原为单个 \n;
      • Linux / macOS 无此转换,文本、二进制模式行为一致;
  2. 二进制模式核心作用
    • 添加 ios_base::binary 后,所有字节原样落地,不会插入、替换任何换行相关字符,适合结构体、数组、图片、程序等二进制数据持久化。
  3. 风险场景
    • 使用 write() 序列化数字、结构体时,必须加 binary,否则数值中出现 0x0A 就会多出 0x0D,字节长度错乱,读取数据完全失真。
相关推荐
chh5638 小时前
C++--list
开发语言·数据结构·c++·学习·算法·list
qq_416409138 小时前
性价比高的openclaw选哪家
c++
汉克老师9 小时前
GESP2026年6月认证C++八级( 第三部分编程题(2、堆石子))精讲
c++·排列组合·快速幂·费马小定理·gesp8级·逆元·组合数计算
信竞星球_少儿编程题库9 小时前
2026年全国青少年信息素养大赛算法应用主题赛(星火征途C++小学组复赛真题)
c++
盐焗鹌鹑蛋10 小时前
【C++】AVL树
c++
杜子不疼.10 小时前
【C++】继承—C++的秘密武器,get父类的智慧
开发语言·c++
ShineWinsu10 小时前
对于Linux:基于UDP实现简单聊天室功能
linux·c++·面试·udp·笔试·进程·简单聊天室
chase_my_dream10 小时前
2D-SLAM 真实数据处理与多传感器工程落地:时间同步、异常过滤、标定对齐和系统调试
c++·人工智能·2d-slam
c2385611 小时前
《序列 DP:C++ 中的“最长”套路与编辑距离》
c++·算法·动态规划
鱼子星_11 小时前
【C++】类和对象(下)——初始化列表,类型转换,static成员,友元,内部类,匿名对象,编译器的优化拓展
c语言·c++·笔记