在编写一些代码来更新二进制文件中的位置时,我发现了一些奇怪的东西。请考虑以下示例代码:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
char tmp;
string s;
fstream fs;
fs.open("test.txt", fstream::out);
fs << "blub" << endl;
fs.close();
fs.open("test.txt", fstream::in);
fs >> s;
cout << s << endl;
fs.close();
fs.open("test.txt", ios::in|ios::out|ios::binary);
if (!fs.is_open() || !fs.good())
cerr << "could not open!" << endl;
fs.read(&tmp, 1);
fs.read(&tmp, 1);
//fs.tellg(); //<-- required to fix for old g++?
const char *c = "ah";
fs.write(&c[0], 1);
fs.write(&c[1], 1);
fs.close();
fs.open("test.txt", fstream::in);
fs >> s;
cout << s << endl;
}
在最近的g ++版本中(至少在6.2.1版本中),我可以只读取然后写一些没有问题的字节 - 在这个例子中你得到了正确的输出:
blub
blah
然后我用g ++ 4.7.2编译代码,突然更新没有效果,即第二个输出仍然是“blub”,除非我添加fs.tellg()或fs.tellp ()。我发现了this的问题,但据我了解,这是Windows的限制,但我在Linux下工作。
现在我想知道,这是旧g ++中的一个错误还是我做错了,并且幸运的是现代g ++版本,它只是有效吗?第二个问题,为什么要求当前的位置解决它?
提前致谢!
答案 0 :(得分:2)
现在我想知道,这是旧g ++中的一个错误
不,在这方面g ++没有错误。
或者我做错了
是。您在链接的answer中对此进行了解释。
...如果没有对fflush函数或文件定位函数(fseek,fsetpos或rewind)的干扰调用,输出不应直接跟随输入,并且输入不应直接跟随输出而不进行干预调用到文件定位功能,除非输入操作遇到文件结尾。
哪个来自C标准,但通过以下方式相关:
读取和编写由basic_filebuf类对象控制的序列的限制与使用标准C库FILE读取和写入的限制相同。
有一个错误,但它在您的代码中。您的计划不符合标准规定的要求。
但据我了解,这是Windows下的限制
可能是这种情况,但更一般地说,限制是在C ++(和C)规范中。标准库是否具有限制对库是否符合标准没有影响。任何依赖于不存在限制的代码都不符合标准。
并且[我]幸运地使用现代g ++版本
有人可能会说你不走运。当程序不起作用而你发现了这个错误时,这是一个好运。
第二个问题,为什么要求当前的位置解决它?
我怀疑tellg
是否足以使您的程序符合标准。所以,我会说它“偶然”修复了这个程序。
您应该使用std::flush(fs);
代替。
这是否意味着新版本符合LESS标准?
不,这两个版本的g ++在这方面同样兼容。你的计划不是。