【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,字节长度错乱,读取数据完全失真。
相关推荐
码匠许师傅2 小时前
【C++ 面试真题】聊聊 C++ 的移动语义与右值引用
java·c++·面试
小小龙学IT4 小时前
DuckDB 深度实战:用 C++ 在进程内跑一个「分析型数据库」
数据库·c++
知无不研5 小时前
lambda表达式的使用(3)
开发语言·c++·lambda
C++ 老炮儿的技术栈7 小时前
基于Qt实现轻量化本地音乐播放器
开发语言·c++·qt·c·播放器·音乐
qz_Serene9 小时前
C++:类和对象(上)
开发语言·c++
郝学胜-神的一滴10 小时前
干货版《算法导论》17:二叉树核心原理、遍历逻辑与高阶实操全解
数据结构·c++·python·算法·计算机·编程
hetao173383710 小时前
2026-08-09~08-14 hetao1733837 的刷题记录
c++·算法
间歇性努力持续性发呆的野生快乐选手13 小时前
栈的性质(进栈,出栈,访问)
数据结构·c++
旖旎夜光13 小时前
LeetCode 904:水果成篮(滑动窗口) —— 题解
数据结构·c++·算法·leetcode·滑动窗口
hansang_IR14 小时前
【题解】P14468 [COCI 2025/2026 #1] 和谐 / Harmonija(线段树 DDP 版本)
c++·算法·动态dp