即使在二进制模式下,Std::ofstream也写入

std::ofstream writes even in binary mode

本文关键字:ofstream Std 二进制 模式      更新时间:2023-10-16

我正在尝试使用std::ofstream()编写UTF-16编码文件。即使在二进制模式下,"n"也被写成"rn"。示例代码:

std::string filename = ...
std::ofstream fout(filename, std::ios_base::binary);
fout.write("xffxfe", 2);
fout.write("n", 2);
fout.close();
结果文件的十六进制数据为:
ff fe 0d 0a 00
我一定是做错了什么。有什么办法可以防止0x0d被写入吗?

我使用的是MS VisualStudio 2013。

Update:它莫名其妙地开始按预期工作。这是机器里的鬼。

您发送了4个字节要输出。在输出中观察到5个。

您没有使用二进制模式。没有其他方法可以使用。write(buf, 2)和。write(buf, 2)并获得5字节的输出。

很可能,在搞乱/玩弄东西时,(当人们试图弄清楚为什么奇怪的行为时总是这样做)你改变的某些东西导致它实际上断言二进制模式。

如果您之前尝试输出到STDOUT或STDERR,则完全有可能windows自动将'r'添加到流中,因为STDOUT和STDERR几乎总是文本,这可能会覆盖您将其放入二进制模式的尝试。(不,真的。不,你用的是Visual Studio,这真的是。是的,如果你使用cygwin,这不是真的,但你使用vs)

这是设计。n字符被转换为平台的EOL标记,因此ofstream::write函数可以正确地解释它。如果你想写一个二进制文件,你不能使用特殊的文本字符。

澄清:我设法对编译器正在做的事情造成了一点混乱。基本上,n是一个特殊字符,表示"EOL/行结束",这取决于编译的平台。

现在write()函数正在接受一个字节数组来写入流。C标准并没有真正区分字符串(在C中技术上没有这样的东西)和字符(或字节)数组,所以它让你摆脱了这一点。在编译期间发生的事情是,这些行被转换成这样的内容:

fout.write({255, 254, 0}, 2);   // "xffxfe"
fout.write({13, 10, 0, 0}, 2);  // "n"
fout.close();