【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,字节长度错乱,读取数据完全失真。
相关推荐
蜗牛一步步往上爬1 小时前
第十六章 C++语言在深度学习中的应用
开发语言·c++·深度学习
wo_jack5 小时前
C++ 入门笔记(十六):第16课 vector 模拟实现十问十答 —— 从三指针到迭代器失效
c++·后端·面试·stl·vector
D e re k ZH5 小时前
C++ 标准库算法全景指南
数据结构·c++·算法
雪落漂泊6 小时前
C++算法 二分查找篇(上)
开发语言·c++·算法
不会算法的笨小孩8 小时前
异常的使用以及会出现的问题
开发语言·c++·c++11·异常
Hhy_110710 小时前
《C++深度解构06》手撕 string —— 从底层内存管理到深浅拷贝彻底吃透
c语言·开发语言·c++·学习·visual studio
青少儿编程课堂11 小时前
蓝桥杯青少组图形化省考报名倒计时·全国青少年信息素养大赛·电子学会图形化考级:校园黑白棋人机对战解析
c++·python·算法·bfs·信息学竞赛
YSL07012411 小时前
C++基础
开发语言·c++
eggwyw12 小时前
关于C++为什么不加入垃圾回收机制解析
开发语言·c++
曦樂~21 小时前
Cpp面筋
c语言·c++