c++ - 为什么 std::ofstream 会在没有 std::ios_base::trunc 的情况下截断?
问题描述
根据这个 C++ 参考:http : //www.cplusplus.com/reference/fstream/ofstream/ofstream/ ,默认的打开模式std::ofstream
是 is并且它没有提到隐含的其他模式。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 错了吗?或者行为依赖于什么?
解决方案
explicit basic_ofstream(const char* s, ios_base::openmode mode = ios_base::out);
因此,默认模式ofstream
为out
. 但是,根据[tab:filebuf.open.modes],out
两者out | trunc
都对应于 stdio 等价物"w"
,因此它们是等价的。根据C11 7.21.5.3:
w
: 截断到零长度或创建文本文件进行写入
因此,说默认模式是out
正确的,说默认模式等价于 也是正确的out | trunc
。这是有保证的行为。
另一方面,根据[fstream.cons]/itemdecl:2:
explicit basic_fstream( const char* s, ios_base::openmode mode = ios_base::in | ios_base::out);
因此,默认模式fstream
为in | out
. 根据[tab:filebuf.open.modes],in | out
对应于"r+"
,而in | out | trunc
对应于"w+"
,因此它们不等价。根据C11 7.21.5.3:
r+
:打开文本文件进行更新(读取和写入)
w+
:截断为零长度或创建文本文件进行更新
因此,fstream
除非您指定 ,否则不会截断trunc
。请注意,如果所需的文件不存在,r+
将失败而不是创建文件。相反,在这种情况下w
,w+
两者都会创建一个新文件。
(另见:fopen
关于 cppreference)
推荐阅读
- java - 为什么我得到一个 sqlexception 永远不会在相应的 try 语句错误的正文中抛出
- javascript - 在 Postman 中使用 math.js
- c++ - 如何将struct的函数转换为C
- python - Django:从用户序列化程序获取用户配置文件
- reactjs - React Router 在隐身模式下无法识别身份验证令牌(AAD B2C)
- c++ - 从clang c++20模块中导出全局变量
- databricks - 在 Azure Databricks 中连接到 Azure 数据库时出现超时错误
- jquery - 在jquery中访问json值的问题
- c - 请帮助我使用 C(终端)中的菜单,因为我的教授不能
- python - joblib 并将新行添加到数据框