为什么 std::ofstream 在没有 std::ios_base::trunc 的情况下截断? [复制]

2024-01-05

根据这个 C++ 参考:http://www.cplusplus.com/reference/fstream/ofstream/ofstream/ 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 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有错吗?或者行为取决于什么?


Per [ofstream.cons]/itemdecl:2 http://eel.is/c++draft/ofstream.cons#itemdecl:2:

explicit basic_ofstream(const char* s,
                        ios_base::openmode mode = ios_base::out);

因此,默认模式为ofstream is out。然而,每[选项卡:filebuf.open.modes] http://eel.is/c++draft/filebuf.members#tab:filebuf.open.modes, out and out | trunc两者都对应于 stdio 等效项"w",所以它们是等价的。每C11 7.21.5.3 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#%5B%7B%22num%22%3A695%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C-27%2C816%2Cnull%5D:

w:截断到零长度或创建用于写入的文本文件

因此,默认模式是正确的out,并且说默认模式相当于out | trunc。这是有保证的行为。

另一方面,每[fstream.cons]/itemdecl:2 http://eel.is/c++draft/fstream.cons#itemdecl:2:

explicit basic_fstream(
  const char* s,
  ios_base::openmode mode = ios_base::in | ios_base::out);

因此,默认模式为fstream is in | out. Per [选项卡:filebuf.open.modes] http://eel.is/c++draft/filebuf.members#tab:filebuf.open.modes, in | out对应于"r+", while in | out | trunc对应于"w+",所以它们不等价。每C11 7.21.5.3 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#%5B%7B%22num%22%3A695%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C-27%2C816%2Cnull%5D:

r+:打开文本文件进行更新(读取和写入)
w+:截断到零长度或创建文本文件以进行更新

所以,fstream除非您指定,否则不会截断trunc。 请注意,如果所需的文件不存在,r+将失败而不是创建文件。相比之下,w and w+在这种情况下,两者都会创建一个新文件。

(也可以看看:fopen https://en.cppreference.com/w/c/io/fopen在 cppreference 上)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 std::ofstream 在没有 std::ios_base::trunc 的情况下截断? [复制] 的相关文章

随机推荐

  • 什么是域错误

    在 C 中 有一个 域错误 的基类 std domain error 我不明白在什么情况下我应该在代码中抛出域错误 所有其他异常基类都非常不言自明 我很确定 std domain error 本身与互联网域名无关 因此请解释域错误是什么类别
  • 如何用intellij中的空格序列替换文件中的所有制表符?

    给定项目中的一个文件 我希望能够用空格替换文件中的所有制表符 intellij 有什么办法可以做到这一点吗 转到编辑 转换缩进 然后分别选择 到空格 或 到制表符 它在文档中 改变缩进 http www jetbrains com idea
  • Python 是否内置了针对特殊字符和/或标点符号的字符串验证?

    Python 有str isalnum str isdigit str isupper str islower str isalpha 但是它是否有任何内置的字符串验证检查特殊字符或标点符号 即 等 标准string模块提供string p
  • 如何以编程方式获取Linux进程的堆栈起始地址和结束地址?

    对于单线程程序 我想检查给定的虚拟地址是否在进程的堆栈中 我想在用 C 编写的进程中执行此操作 我正在考虑读书 proc self maps找到标记为 stack 的行 以获取进程堆栈的开始和结束地址 思考这个解决方案让我产生了以下问题 p
  • java系统范围的键盘和鼠标状态

    有没有办法在系统范围内侦听鼠标和键盘事件 而不将它们从系统队列中取出 例如 有没有办法设置一个恶魔 比如说 它会监听并报告每个键盘和鼠标事件 使用纯Java 是不可能的 但是您可以使用 JNI Java 本机接口 它适用于用 C 编写并本机
  • UPDATE 语句包含在 IF EXISTS 块中

    我正在尝试编写一个更新列的 DML 脚本 但我想确保该列首先存在 因此我将其包装在 IF EXISTS 块中 IF EXISTS SELECT FROM INFORMATION SCHEMA COLUMNS WHERE TABLE NAME
  • 如果消息被编辑,防咒骂系统将不起作用

    基本上 如果您说了一些不是脏话的内容 但随后将消息编辑为脏话 机器人将不会检测到它 我该如何解决 这是我的代码 client event async def on message message if message author bot
  • 通过选择散点图上的点来更新虚线表

    我正在制作仪表板 这是我的代码 IMPORT SECTION import dash import dash table import dash core components as dcc import dash html compone
  • 非静态类与静态类相比有哪些优点?

    非静态类与静态类相比有哪些优点 静态类不需要实例化 所以我们可以直接使用ClassName MemberName 那么非静态类有什么用呢 静态类与非静态类基本相同 但有一个区别 静态类不能被实例化 换句话说 不能使用new关键字来创建类类型
  • Sublime Text 3 上的 Python 3.4

    我按照以下步骤在 Sublime Text 3 上运行 Python 3 选择菜单 工具 gt 构建 gt 新建构建系统 我输入了以下内容 cmd python3 file selector source python file regex
  • 显示同一类方法的已弃用警告

    使用 eclipse 我希望尽快看到警告any我使用的方法标记为 Deprecated 如果是这样 方法调用将被正确划掉 但如果该方法源自同一个类 则 Eclipse 不会发出警告 请参阅下面的屏幕截图 为了更好地重现 我还将提供文本形式的
  • python 如何在数据框中执行以下操作

    df1 pd DataFrame Year 1A 2A 3A 4A 5A Tval1 1 9 8 1 6 Tval2 34 56 67 78 89 它看起来更像这样 我想更改它 使其看起来像这样 第二列移动到单独的行下方 想法是从中获取数字
  • 如何确定 Android View 是否被其他 View 遮挡

    我想检查特定视图 例如 TextView 是否被任何其他视图 例如导航抽屉但不一定 遮挡 我明白了 即使视图被其他视图 布局遮挡 View GetVisibilty View IsShown 也会返回 true None
  • constexpr 比 const 更“恒定”吗?

    C 编程语言第四版 Bjarne Stroustrup 强调我的 2 2 3 常数 在一些地方 语言规则需要常量表达式 例如 数组边界 2 2 5 7 3 大小写标签 2 2 4 9 4 2 一些 模板参数 第 25 2 节 和使用 con
  • io.sockets.emit 和广播有什么区别?

    io sockets emit 和 socket broadcast emit 有什么区别 广播是否只向每个人发送 但发送它的套接字除外 看起来它们可以互换使用 io sockets on connection function socke
  • 捕获when.js未处理的拒绝

    我想捕获when js 未处理的拒绝 以便我可以记录它们 为了实现这一点 我重写了 console warn 但是它可以记录除 when js 以外的我不感兴趣的内容 ref https github com cujojs when blo
  • > /dev/null 如何消耗输出流?

    我用过 dev nullbash 编程中的很多内容都将不必要的输出发送到黑洞中 例如 这个命令 echo foo bar gt dev null 将不会echo任何事物 我读过 dev null是一个空文件 用于通过重定向处理不需要的输出
  • 启动自定义 URL 的图像 - 故事板或资产目录

    我试图在自定义 url 启动应用程序时拥有自定义启动图像 有没有办法指定自定义故事板 UILaunchStoryboardName 或资产目录中的图像以在此场景中使用 从 iOS 8 3 开始这是不可能的
  • 如果目标不为空,自动映射器可以忽略目标/仅更改空字段

    背景 我正在开发一个网络服务 我希望允许具有空字段的输入表示 不进行更新 输入对象与数据库模型非常相似但不完全相同 因此我们使用自动映射器来进行转换 因此 在更新的情况下 我希望能够获取现有值 使用它们覆盖输入中的任何空字段 然后保存它以执
  • 为什么 std::ofstream 在没有 std::ios_base::trunc 的情况下截断? [复制]

    这个问题在这里已经有答案了 根据这个 C 参考 http www cplusplus com reference fstream ofstream ofstream http www cplusplus com reference fstr