使用std :: ios_base :: binary有什么意义?

时间:2014-11-18 11:22:05

标签: c++ stl iostream eol

我在Window下阅读Linux文件时出现问题。以下是问题讨论:Using fstream::seekg under windows on a file created under Unix

通过打开指定了std::ios_base::binary文本文件来解决该问题。

但这个模式的实际意义是什么?如果已指定,您仍然可以将文件用作文本文件(使用mystream << "Hello World" << std::endl进行写入并使用std::getline进行阅读。)

在Windows下,唯一的区别是,我注意到mystream << "Hello World" << std::endl使用:

    如果未指定0x0D 0x0A(EOL和回车),
  • std::ios_base::binary作为行分隔符
  • 0x0A作为行分隔符,如果指定了std::ios_base::binary(仅限EOL)

打开使用std::ios_base::binary生成的文件时,记事本不能巧妙地显示行。像vi或Wordpad这样的优秀编辑确实会展示它们。

使用和不使用std::ios_base::binary生成的文件之间是否真的唯一不同?文档说Consider stream as binary rather than text.,这到底是什么意思?

如果我不关心在记事本中打开文件并希望std::ios_base::binary始终有效,那么始终设置fstream::seekg是否安全?

3 个答案:

答案 0 :(得分:7)

二进制和文本模式之间的区别在于实现 定义,但只涉及最低级别:他们不改变 <<>>之类的含义(插入和提取文本 数据)。此外,正式地,输出除了少数不可打印的所有 如果文件是文本,则字符(如'\n')是未定义的行为 模式。

对于最常见的操作系统:在Unix下,没有区别;两者都是 相同。在Windows下,'\n'内部将映射到两者 外部字符序列CR,LF(0x0D,0x0A),0x1A将是 在阅读时被解释为文件的结尾。更具异国情调(主要是 然而,操作系统,它们可以完全不同 操作系统级别的文件类型,可能无法读取文件 文本模式,如果它是以二进制模式写入,反之亦然。或者您 可以看到不同的东西:在行尾有额外的空白区域,或者 在二进制模式下没有'\n'

关于始终设置std::ios_base::binary:我的政策 可移植文件是确切地决定我希望它们如何格式化,设置 二进制,并输出我想要的。这通常是CR,LF,而不仅仅是 LF,因为那是网络标准。另一方面,大多数 Windows程序只有LF没有问题,但我遇到过 不止一些Unix程序有CR,LF的问题;哪一个 主张系统地使用LF(这也更容易)。干 这样的事情意味着无论是否,我得到相同的结果 我在Unix或Windows下运行。

答案 1 :(得分:0)

文本流与二进制流的含义是特定于平台的,有些不可预测。

但就流行平台而言,它很简单:在Linux和MacOS X上,没有区别。在Windows上,唯一的区别是内部\n已在外部流中转换为\r\n

答案 2 :(得分:0)

我发现(通过减少两个小时的工作以试图了解正在发生的事情),确实存在一种情况,即指定std::ios_base::binary确实会带来很大的改变。

std::vector<char> data{ 0x01, 0x02, 0x0A, 0x0B };
{
    std::fstream tfat;
    tfat.open( "binary", std::ios_base::out | std::ios_base::binary );
    tfat.write( &(data[0]), data.size() );
    tfat.close();
}
{
    std::fstream tfat;
    tfat.open( "not_binary", std::ios_base::out );
    tfat.write( &(data[0]), data.size() );
    tfat.close();
}

然后,“二进制”文件包含4个字节:0x01, 0x02, 0x0A, 0x0B 但是“ not_binary”文件包含5个字节:0x01, 0x02, 0x0D, 0x0A, 0x0B

在0x0A(\r)之前插入了

0x0D(\n)。当我写4个字节时,我希望最后在文件中有4个字节。

因此,这使我意识到,即使不使用std::ios_base::binary运算符,也必须在将数据写入文件时使用<<