【问题标题】:Subsequent read and write operation on Files with C++使用 C++ 对文件进行后续读写操作
【发布时间】:2011-11-28 11:41:51
【问题描述】:

我有一个二进制文件 (test.bin),其中有 2 个无符号整数值,分别为 1000 和 4000。 使用下面的代码,我想用第一个写入函数将第一个数字更改为 5000,然后我想读取第二个数字并用 4000-2000 = 2000 重写它。 但是,程序将 1000 更改为 5000,但没有将 4000 更改为 2000。即使我使用 file.flush() 或 file.sync(),它也没有任何效果。 有趣的是,当我输入 file.tellg() 或 file.tellp() 时,它可以按我的意愿工作。 (我偶然发现的) 这在 Linux 和 Windows 上都会发生。在 Linux 上,我尝试用 g++ 编译它。 sizeof(unsigned int)=4 并且我确信程序可以打开 test.bin。

#include <fstream>
#include <iostream>

using namespace std;

int main(){
    fstream file;
    unsigned int data, buffer;
    data=5000;
    file.open("test.bin", ios::binary | ios::in | ios::out);

    file.write((char*)&data,4); // will change first number to 5000

    // file.flush();  // Nothing changes if I delete comment signs.

    // file.tellp();  // Program works correctly if I uncomment this. 
    // file.tellg();  // Program works correctly if I uncomment this.

    file.read((char*)&buffer, 4);  // position pointer should be at the beginning of the 2nd number

    file.seekp(-4, ios::cur); // Since internal pointer is at the end of the file after the read(), I manually put it back to the beginning of the 2nd number.

    buffer-=2000;
    file.write((char*)&buffer,4); // Now, it should rewrite 2nd number with 2000. 

    file.close();
    return 0;
}

【问题讨论】:

  • 我不明白你为什么要搜索,读完后 fp 应该在第二个数字的开头。
  • 没错,我自己没有找到做 seekp 的解释。它应该正好在第二个数字的开头,但是当我执行它时它不起作用。但是,当我取消注释 seekg 时,它起作用了!我不知道为什么……很奇怪。

标签: c++ file binary


【解决方案1】:

宾果!您偶然发现了 C++ 语言的一个非常晦涩、几乎不成文且充其量是模棱两可的要求。我试图主张将其从 G++ 中删除,并为此编写了一个补丁,但遇到了维护者的冷淡反应,在我证明它可以完成后被接受了无需大量重新设计。

如果内存服务,C++ 规范提到文件流与 C &lt;stdio.h&gt; 流使用相同的语义,而 C 规范说您必须 seek 在读取和写入同一文件之间。

这是错误:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45708

讨论#1:http://gcc.gnu.org/ml/libstdc++/2010-09/msg00079.html

讨论#2:http://gcc.gnu.org/ml/libstdc++/2010-09/msg00104.html

编辑:我需要更好的记忆力!实际上, 已于 2010 年 9 月 22 日提交到 GCC 4.6.0。其余未提交的编辑与在 I/O 期间更改语言环境编解码器方面有关。

跟踪已接受更改的错误:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45628

【讨论】:

  • 那么在写入和读取之间添加tellg是必需的吗?但是为什么flush不起作用呢?
  • 非常感谢。这些非常有用。
  • @user:是的,问题在于解决文件位置,而不仅仅是刷新。碰巧的是,tellg 函数执行刷新,flush 函数确实确定了位置……无论如何,这个要求是愚蠢的。我的补丁还消除了不必要的冲洗,IIRC。
  • @user:重要更新!阅读到讨论的最后——实际上更改已被接受,因此您只需要升级编译器。
猜你喜欢
  • 2018-03-28
  • 1970-01-01
  • 1970-01-01
  • 2018-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多