std::ofstream默认是截断还是追加?

26

如果您调用std::ofstream构造函数而没有使用openmode标志,那么默认标志是ios_base::out。但这是否意味着ios_base::truncios_base::app

换句话说,如果您的文件系统中已经有一个非空文件 "past.txt",然后您调用:

std::ofstream stream( "past.txt" );
stream << "new content";

"新内容"会被添加到"past.txt"之前的内容中还是会替换之前的内容?


4
我感觉这个问题是基于错误的参考选择而提出的。这个链接应该更好:http://en.cppreference.com/w/cpp/io/basic_filebuf/open。 - LogicStuff
ios_base::outios_base::out | ios_base::trunc相同。我找不到一个好的参考链接,但是谷歌搜索命中了一些教科书 - CAB
根据LogicStuff的链接,ofstream构造函数的默认值是“out”,在basic_filebuf::open中的行为与“out|trunc”相同,因此会进行截断。 - Useless
2
我投票关闭此问题,因为答案可以在正确的参考资料中轻松找到。(只需亲自测试即可证明) - πάντα ῥεῖ
1
听起来这可能是另一个cplusplus.com有什么问题的案例,不过这次只是遗漏了... - jaggedSpire
1个回答

56

简短版

默认情况下会截断。


中等版

标准规定有些含糊,但最终可以归结为相当于 fopen(const char*, "w")(27.9.1.4 [filebuf.members]),然后我们就可以查看 ISO C 7.9 标准了。

在查看该标准时,我们可以找到 §7.19.5.3,“fopen 函数”,其中指定了传递“w”时的行为:

w 会将文件截断为零长度或创建一个文本文件以便写入


长版

如果您想自己跟踪这个问题,请从 27.9.1.11 [ofstream.cons] 开始,其中描述了构造函数的行为为

效果:构造一个 basic_ofstream<charT,traits> 类型的对象,使用 basic_ostream(&sb)) 初始化基类并使用 basic_filebuf<charT,traits>() 初始化 sb (27.7.3.2, 27.9.1.2),然后调用 rdbuf()->open(s, mode|ios_base::out)。如果该函数返回空指针,则调用 setstate(failbit)

其中 rdbuf() 返回 basic_filebuf<charT,traits>*(27.9.1.13 [ofstream])

这将引导我们到 27.9.1.1 [filebuf],更具体地说,是 27.9.1.4 [filebuf.members],它描述了open函数的行为:

basic_filebuf<charT,traits>* open(const char* s, ios_base::openmode mode);

作用:如果is_open() != false,则返回空指针。否则,按照要求初始化filebuf。 然后,如果可能,打开一个名为NTBS s的文件(就像调用std :: fopen(s,modstr)一样)。 NTBS modstrmode&~ios_base :: ate确定,如表132所示。 如果模式不是表中显示的标志组合,则打开失败。

NTBS:以空字符结尾的字节字符串

表132描述了C ++ ios_base :: openmode和C-style stdio字符串之间的等价规则:

<b>Table 132</b> — File open modes
|
|   'ios_base' flag combination   | 'stdio' equivalent |
| binary | in | out | trunc | app |                    |
|        |    |  +  |       |     |        "w"         |
|                     etc...                           |
这导致我们看到同一页上的一个脚注,其中声明了函数签名fopen(const char*, const char*)fseek(FILE*, long, int),这些声明在<cstdio>(27.9.2)中。可预测地将我们带到27.9.2[c.files],该部分提供了几乎无用的表格134,但随后引用了C标准:

另见:ISO C 7.9,Amendment 1 4.6.2。


我在本答案的主要部分谈到了这个内容。

那么答案是什么? - A. Smoliak
1
@A.Smoliak,“std::ofstream默认是截断还是追加?”这个问题的答案是“截断”。 - AndyG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接