(Note: sizeof(character) == 68 bytes)
I am having issues with fstream::seekg()/seekp(). It seems like when one is invoked to modify the get or put pointer, the other pointer follows it instead of staying in place. Example:

charfile.seekp(0,ios::beg);
cout << endl << "Put pointer is at " << charfile.tellp() << " bytes.";
charfile.seekg(0,ios::beg);
cout << endl << "Get pointer is at " << charfile.tellg() << " bytes.";
cout << endl << "Initializing slots..." << endl;
for(int i=0;i<CHARSLOTS;i++)
{
	charfile.read((char*)(charbuf),sizeof(character));
	cout << endl << "Get pointer is at " << charfile.tellg() << " bytes.";
	cout << endl << "Put pointer is at " << charfile.tellp() << " bytes.";

Output of above code after 1 iteration of the for loop is:

Put pointer is at 0 bytes.
Get pointer is at 0 bytes.
Initializing slots...

Get pointer is at 68 bytes.
Put pointer is at 68 bytes.

As I understand it, fstream::read() advances the get pointer by however many bytes it read. In this case, it also advances the put pointer by an equivalent amount. What gives?

I have another fstream issue, but one problem at a time.

Recommended Answers

All 5 Replies

this is an issue in the c++98 standard.
this has been addressed by The Library Working Group (LWG), the ISO subcommittee responsible for making changes to the std c++ library. a proposed resolution to this http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#136 has been adopted in the Tokyo meeting of the LWG (2000?) and should make its way into the standard library implementations.

Thank you. It is surprising to see such a mistake in the implementation. Are seekp()/seekg() not often used in serious programming?
I could just use seekg() only in place of seekp() but that just seems like a bad idea. What would be a good workaround for this issue?

> I could just use seekg() only in place of seekp() but that just seems like a bad idea.
it is a bad idea; your code would break at some future date (when implementations are updated).

> What would be a good workaround for this issue?
a simple workaround is to use two different stream objects, one for output and another for input. if output is to be instantaneously visible to the input, the two streams have to be tied. and you may want to disable buffering for input.

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std ;

int main()
{
    {
        // create a test file
        ifstream in( __FILE__ ) ;
        ofstream out( "/tmp/test.txt" ) ;
        out << in.rdbuf() ;
    }
    {
        fstream in_file( "/tmp/test.txt" ) ; 
        fstream out_file( "/tmp/test.txt" ) ;
        in_file.tie( &out_file ) ; // *** for coherence ***
        in_file.rdbuf()->pubsetbuf(0,0) ; // *** if required *** 
        
        cout << "tellp: " << out_file.tellp() << '\n' ;
        cout << "tellg: " << in_file.tellg() << '\n' ;
        out_file.seekp( -255, ios::end ) ;
        cout << "tellp: " << out_file.tellp() << '\n' ;
        cout << "tellg: " << in_file.tellg() << '\n' ;
        in_file.seekg( 111, ios::beg ) ;
        cout << "tellp: " << out_file.tellp() << '\n' ;
        cout << "tellg: " << in_file.tellg() << '\n' ;
        cout << "--------------------\n" ;
        out_file << "\n\n******* this is a test *********\n\n" ;
        string str ;
        for( int i=0 ; i<5 ; ++i )
          if( getline( in_file, str ) ) cout << str << '\n' ;
        cout << "--------------------\n" ;
    }
    system( "/bin/cat /tmp/test.txt" ) ; 
}

I tried running your code, and sure enough both get and put pointers work independently. However, I am unable to duplicate this success even with separate streams. Here is a complete function which is giving me the problem:

void initializeslots(character* dummy)
{
	character* charbuf;
	charbuf = new character;
	ifstream charread;
	ofstream charfile;

	charread.open("character.dat",ios::binary|ios::in);
	if(charread.fail())
	{
		cerr << "Failed to open character.dat for reading!" << endl;
		return;
	}
	charfile.open("character.dat",ios::binary|ios::out);
	if(charfile.fail())
	{
		cerr << "Failed to open character.dat for writing!" << endl;
		return;
	}

	cout << "Currently, struct character is " << sizeof(character) << " bytes long." << endl;

	charread.seekg(0,ios::beg);
	charfile.seekp(0,ios::beg);
	cout << "Initializing slots..." << endl;
	for(int i=0;i<CHARSLOTS;i++)
	{
		charread.read((char*)(charbuf),sizeof(character));
		if(charread.fail())
			cerr << "Failed to read from file." << endl;
		if(charread.bad())
			cerr << "Badbit set while trying to read." << endl;
		if(charread.eof())
			cerr << "EOF reached while trying to read." << endl;
		cout << "Get pointer is at " << charread.tellg() << " bytes." << endl;
		charfile.write((char*)(dummy),sizeof(character));
		if(charfile.fail())
			cerr << "Failed to write to file." << endl;
		if(charfile.bad())
			cerr << "Badbit set while trying to write." << endl;
		if(charfile.eof())
			cerr << "EOF reached while trying to write." << endl;
		cout << "Put pointer is at " << charfile.tellp() << " bytes." << endl;
	}
	cout << "Finished writing dummy slots." << endl;
	charread.close();
	charfile.close();
	return;
}

The output is:

Currently, struct character is 68 bytes long.
Initializing slots...
Failed to read from file.
EOF reached while trying to read.
Get pointer is at -1 bytes.
Put pointer is at 68 bytes.
Failed to read from file.
EOF reached while trying to read.
Get pointer is at -1 bytes.
Put pointer is at 136 bytes.
Failed to read from file.
EOF reached while trying to read.
Get pointer is at -1 bytes.
Put pointer is at 204 bytes.
Failed to read from file.
EOF reached while trying to read.
Get pointer is at -1 bytes.
Put pointer is at 272 bytes.
Failed to read from file.
EOF reached while trying to read.
Get pointer is at -1 bytes.
Put pointer is at 340 bytes.
Failed to read from file.
EOF reached while trying to read.
Get pointer is at -1 bytes.
Put pointer is at 408 bytes.
Failed to read from file.
EOF reached while trying to read.
Get pointer is at -1 bytes.
Put pointer is at 476 bytes.
Failed to read from file.
EOF reached while trying to read.
Get pointer is at -1 bytes.
Put pointer is at 544 bytes.
Finished writing dummy slots.

Simple troubleshooting revealed that charread.read() failed as soon as I added the code to open the same file for the output stream (charfile). Something is wrecking the input stream, and besides that the presence of the output stream is causing it, what is the actual mechanism?

> charread.read() failed as soon as I added the code to open the same file
> for the output stream (charfile). Something is wrecking the input stream,
> and besides that the presence of the output stream is causing it charfile.open("character.dat",ios::binary|ios::out); is truncating the stream to zero size (default while opening only for output).

void initializeslots(character* dummy)
{
	character* charbuf;
	charbuf = new character;
	ifstream charread;
	fstream charfile;

	charread.open("character.dat",ios::binary|ios::in);
	if(charread.fail())
	{
		cerr << "Failed to open character.dat for reading!" << endl;
		return;
	}
	charfile.open("character.dat",ios::binary);
        // ...

should fix it.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.