根据此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 | 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();
}
Run Code Online (Sandbox Code Playgroud)
无论是Windows上的g ++ 8.1和Linux上的g ++ 6.3,Apache文档似乎都是正确的。大文件被截断,在第二个文件流中写入较短的字符串后,没有任何内容。
为什么会这样呢?cplusplus.com错误吗?抑或行为令人沮丧?
每个[ofstream.cons] / itemdecl:2:
Run Code Online (Sandbox Code Playgroud)explicit basic_ofstream(const char* s, ios_base::openmode mode = ios_base::out);
因此,的默认模式ofstream是out。然而,每[标签:filebuf.open.modes] ,out并且out | trunc都对应于标准输入输出等效"w",所以它们是等价的。根据C11 7.21.5.3:
w:截短为零长度或创建要写入的文本文件
因此,正确的说默认模式是out,正确的说默认模式等于out | trunc。这是有保证的行为。
另一方面,根据[fstream.cons] / itemdecl:2:
Run Code Online (Sandbox Code Playgroud)explicit basic_fstream( const char* s, ios_base::openmode mode = ios_base::in | ios_base::out);
因此,的默认模式fstream是in | out。每[标签:filebuf.open.modes] ,in | out对应于"r+",而in | out | trunc对应于"w+",所以它们是不等效的。根据C11 7.21.5.3:
r+:打开文本文件进行更新(读取和写入)
w+:截断长度为零或创建文本文件进行更新
因此,fstream除非您指定,否则不要截断trunc。请注意,如果所需文件不存在,r+将失败,而不是创建文件。相反,在这种情况下w,w+两者都创建一个新文件。
(另请参见:fopen关于cppreference)