I have a binary file (test.bin) which has 2 unsigned int values respectively 1000 and 4000 in it.
With the below code, I want to change the first number to 5000 with the first write function and then I want to read second number and rewrite it with 4000-2000 = 2000.
However, the program changes 1000 to 5000 but it does not change 4000 to 2000. Even though I use file.flush() or file.sync(), it does not have any effect.
Interestingly, when I put file.tellg() or file.tellp(), it works as I want. (I found it out by coincidence)
This happens both on Linux and Windows. On Linux I try to compile it with g++.
sizeof(unsigned int)=4 and I’m sure program can open 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;
}
Bingo! You have stumbled upon a very obscure, almost unwritten and at best ambiguous requirement of the C++ language. I
tried toargued for removing it from G++, and wrote a patch to do so,but met a lukewarm response from the maintainerswhich was accepted after I showed it could be done without a heavy redesign.If memory serves, the C++ specification mentions that file streams work with the same semantics as C
<stdio.h>streams, and the C spec says that you mustseekbetween reading and writing to the same file.Here is the bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45708
Discussion #1: http://gcc.gnu.org/ml/libstdc++/2010-09/msg00079.html
Discussion #2: http://gcc.gnu.org/ml/libstdc++/2010-09/msg00104.html
EDIT: I need a better memory! Actually that was committed on September 22, 2010, into GCC 4.6.0. The remaining edits which weren’t committed related to changing the locale codecvt facet during I/O.
The bug tracking the accepted changes: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45628