1

给定以下代码:

std::ofstream stream("somefile");

if (!stream)
{
   return 1;
}

调用.write(....)并使用stdc++libc++时,流处于二进制模式 ( std::ios::binary)。

但是,当使用MSVC (2015/2017RC1)时,它似乎处于文本模式或奇怪的状态,因为生成的文件比实际写入的文件大。

但是,如果我明确设置模式std::ios::binaryMSVC 的行为类似于std::ofstream前面提到的其他标准库的实现。


示例代码:

#include <vector>
#include <cstdio>
#include <fstream>

std::size_t fsz(const char* filename) {
    std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
    return static_cast<std::size_t>(in.tellg());
}

int main() {
   std::ofstream stream("filename");

   if (!stream)
      return 1;

   std::vector<unsigned long long int> v = {0x6F1DA2C6AC0E0EA6, 0x42928C47B18C31A2, 0x95E20A7699DC156A, 0x19F9C94F27FFDBD0};

   stream.write(reinterpret_cast<const char*>(v.data()),v.size() * sizeof(unsigned long long int));

   stream.close();

   printf("expect: %d\n", v.size() * sizeof(unsigned long long int));
   printf("file size: %d\n", fsz("filename"));

   return 0;
}

使用 msvc 运行时上述代码的输出:

expect: 32 
file size: 33

上述代码使用 libc++、stdc++ 运行时的输出:

expect: 32 
file size: 32

差异可能会更大,这取决于写入的数据量和数据的内容。

最后我的问题还是一样,是未定义的还是未指定的行为?


将上述向量更改为以下向量会使示例更明显地了解正在发生的事情。

std::vector<unsigned long long int> v = {0x0A0A0A0A0A0A0A0A, 0x0A0A0A0A0A0A0A0A, 0x0A0A0A0A0A0A0A0A, 0x0A0A0A0A0A0A0A0A};
4

2 回答 2

6

流构造函数使用的默认模式是ios_base::out. 由于没有显式text模式标志,这意味着流以文本模式打开。文本模式仅对 Windows 系统有效,它​​将\n字符转换为 CR/LF 对。在 POSIX 系统上它没有任何作用,并且文本和二进制模式在这些系统上是同义词。

于 2017-02-23T11:11:33.780 回答
3

g++当我使用and在 Windows 上运行您的代码时libstdc++,我得到以下结果:

expect: 32
file size: 33

所以问题不是特定于编译器的,而是特定于操作系统的。

虽然 C++ 使用单个字符\n来表示以字符串结尾的行,但 Windows 使用两个字节0x0D0x0A表示以文件结尾的行。这意味着如果您以文本模式将字符串写入文件,则所有出现的单个字符\n都将使用这两个字节写入。这就是为什么您在示例的文件大小中获得额外字节的原因。

于 2017-02-23T12:58:33.907 回答