Windows std::fstream 在 open() 之后修改文件?

Posted

技术标签:

【中文标题】Windows std::fstream 在 open() 之后修改文件?【英文标题】:Windows std::fstream modify file after open()? 【发布时间】:2020-05-12 14:36:51 【问题描述】:

我对使用标准 c++ 库在 Windows 上工作感到有点困惑。

拥有此代码:

std::fstream _fs;
_fs.open('file.txt', std::fstream::in | std::fstream::out | std::ios_base::ate);

和文件.txt:

abcdefg
SUB

作为 'SUB' 十六进制值 0x1A

在open()之后,没有任何write()或者close(),我发现file.txt被修改了。我发现这个调试代码并在 open() 之后停止它。

file.txt 被修改(也修改文件中的日期)没有 SUB 值,我的意思是,file.txt 现在是:

abcdefg

这是正确的吗?还是我在 open() 模式上做错了什么?

希望有人能指出这一点。

谢谢!

【问题讨论】:

如何查看文件内容?如果你在没有std::ios_base::ate 标志的情况下运行相同怎么办? 嗨,我用 UltraEdit 检查了文件,我在那里打开了文件,当文件更改时它会提醒我并询问我是否要重新加载它。我发现如果我删除 std::fstream::out 标志,文件保持不变,删除 std::ios_base::ate 标志也修改了文件。 这并没有解决问题,而是养成使用有意义的值初始化对象的习惯,而不是默认初始化它们并立即覆盖默认值。在这种情况下,这意味着将std::fstream _fs; _fs.open('file.txt', std::fstream::in | std::fstream::out | std::ios_base::ate); 更改为std::fstream _fs('file.txt', std::fstream::in | std::fstream::out | std::ios_base::ate); @PeteBecker 感谢您的提示,我会记住这一点! 【参考方案1】:

这是因为 MS-DOS 将该字符用作流结束标记,而 Windows 在文本模式下对其进行了一些特殊处理。

Windows documentation for fopen(使用 fstream 最终归结为)说

在文本模式下,CTRL+Z 在输入时被解释为 EOF 字符。在 使用“a+”打开读取/写入的文件,fopen 检查 对于文件末尾的 CTRL+Z 并删除它,如果可能的话。 这样做是因为使用 fseek 和 ftell 在一个文件中移动 以 CTRL+Z 结尾可能会导致 fseek 在 文件。

而 Ctrl+Z 是 SUB 字符。

【讨论】:

不错!我没有读过那个文档,从来没有想过那个操作系统可以在文件中做出那种改变。感谢您的澄清! @webbi 我对此也一无所知,但很好奇并开始寻找解释。感谢您发现这个怪癖并提出问题。

以上是关于Windows std::fstream 在 open() 之后修改文件?的主要内容,如果未能解决你的问题,请参考以下文章

std::fstream 缓冲与手动缓冲(为啥手动缓冲有 10 倍增益)?

为啥 std::fstream 返回 void 而不是 bool

std :: fstream的公共继承和重载运算符<

fstream包含ofstream和ifstream的所有内容? [关闭]

每次读取部分文件到内存中

在C++中如何读取文本中的数据存储为数组变量?