根据此C ++参考:http://www.cplusplus.com/reference/fstream/ofstream/ofstream/,std::ofstream
的默认打开模式为ios_base::out
,并且没有提及其他隐式模式。因此,我希望如果用小文件覆盖大文件,则大文件的“超出”部分应保持不变,并且仅文件的第一部分应由较短的新数据代替。
另一方面,《 Apache C ++标准库用户指南》(http://stdcxx.apache.org/doc/stdlibug/30-3.html)在第30.3.1.2段的注释中指出:“对于输出文件流,打开模式out等同于out | trunc,即,您可以省略trunc标志。但是,对于双向文件流,必须始终明确指定trunc。”
我尝试了以下代码:
#include <fstream>
int main()
{
std::ofstream aFileStream("a.out", std::ios_base::out);
aFileStream << "Hello world!";
aFileStream.close();
std::ofstream aFileStream2("a.out", std::ios::out);
aFileStream2 << "Bye!";
aFileStream2.close();
}
两者,在Windows上为g ++ 8.1,在Linux上为g ++ 6.3,Apache文档似乎是正确的。大文件被截断,在第二个文件流中写入较短的字符串后,什么也没保留。
为什么会这样? cplusplus.com错误吗?还是在行为上pent悔?
答案 0 :(得分:7)
explicit basic_ofstream(const char* s, ios_base::openmode mode = ios_base::out);
因此,ofstream
的默认模式是out
。但是,对于每个[tab:filebuf.open.modes],out
和out | trunc
都对应于stdio等效项"w"
,因此它们等效。根据{{3}}:
w
:截短为零长度或创建要写入的文本文件
因此,可以说默认模式为out
,也可以说默认模式等效于out | trunc
。这是有保证的行为。
另一方面,根据C11 7.21.5.3:
explicit basic_fstream( const char* s, ios_base::openmode mode = ios_base::in | ios_base::out);
因此,fstream
的默认模式是in | out
。对于每个[fstream.cons]/itemdecl:2,in | out
对应于"r+"
,而in | out | trunc
对应于"w+"
,因此它们不是等效的。根据{{3}}:
r+
:打开文本文件进行更新(读写)
w+
:截短为零长度或创建文本文件进行更新
因此,除非您指定fstream
,否则trunc
不会截断。
请注意,如果所需文件不存在,r+
将失败,而不是创建文件。相反,在这种情况下,w
和w+
都会创建一个新文件。
(另请参见:[tab:filebuf.open.modes]关于cppreference)