Cannot reread file

S

Sanyi

I am having some trouble rereading a file for input. Here's the
problem: I have a text file with some data (football scores) in its
lines. First I read them line-by line to figure out how many lines it
has. Afterwards I want to read them again, and this time do some
processing. However I cannot make my program do this. I tried the
following:

############################

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main()
{
ifstream inGameFile;

inGameFile.open( "scores.txt", ios::in );
if ( !inGameFile)
{
cerr << "Failed to open(1).\n";
exit(1);
}

const int LINE = 100;
char stLine[LINE+1];

// count the number of games
int nGames = 0;
while ( inGameFile.getline(stLine, LINE) )
{
nGames++;
}
cout << "A total of " << nGames << " games played.\n";
// Everything works fine this far

if ( !inGameFile)
{
cerr << "No longer open(2).\n"; // inGameFile no longer defined!
//exit(1);
}

cout << inGameFile.tellg() << endl; // result is -1
inGameFile.seekg( 0, ios::beg );
cout << inGameFile.tellg() << endl; // result is -1 again!

// Does not work this way; try to close and reopen:
inGameFile.close();
if ( !inGameFile)
{
cerr << "Failed to close(3).\n";
//exit(1);
}

inGameFile.open( "scores.txt", ios::in );
if ( !inGameFile)
{
cerr << "Failed to open(4).\n";
//exit(1);
} inGameFile.open( "scores.txt", ios::in );

}

############################

The output is:

A total of 1363 games played.
No longer open(2).
-1
-1
Failed to close(3).
Failed to open(4).

############################

Compiler is c++ (GCC) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)

I did something similar on gnu c++ 2.95 under windows, where I could
resolve it by closing and reopening the file. This time it does not
work.

It seems that my inGameFile is automatically closed when I read the
last line, and I can neither move the get pointer nor re-open the
file.

Can someone explain me how can I overcome this?

Thanks,
Sanyi
 
M

Mike Wahler

Sanyi said:
I am having some trouble rereading a file for input. Here's the
problem: I have a text file with some data (football scores) in its
lines. First I read them line-by line to figure out how many lines it
has. Afterwards I want to read them again, and this time do some
processing. However I cannot make my program do this. I tried the
following:

############################

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main()
{
ifstream inGameFile;

inGameFile.open( "scores.txt", ios::in );

Note: 'ifstream' has a 'mode' of ios::in by default.
What you wrote will work, but it's redundant.
if ( !inGameFile)
{
cerr << "Failed to open(1).\n";
exit(1);
}

const int LINE = 100;
char stLine[LINE+1];

Why not a std::string instead of an array?
Then you won't be limited to a size of 'LINE'.
// count the number of games
int nGames = 0;
while ( inGameFile.getline(stLine, LINE) )
{
nGames++;
}
cout << "A total of " << nGames << " games played.\n";
// Everything works fine this far

At this the stream 'inGameFile' is in a 'fail'
state (either because there was an error inside
the 'while' loop above, or it has reached end of
file). This state remains until explicitly reset.
if ( !inGameFile)

So this will always be true.
{
cerr << "No longer open(2).\n"; // inGameFile no longer defined!

No. The stream is still open, but it's in a 'fail'
state.

So right after the 'while' loop, write:

inGameFile.clear();
//exit(1);

If you want to use exit(), you'll need to provide its
declaration (#include <cstdlib> or <stdlib.h>
I recommend you don't use 'exit()' though, because
destructors will not be called. I recommend

return EXIT_FAILURE; // needs #include said:
}

cout << inGameFile.tellg() << endl; // result is -1
inGameFile.seekg( 0, ios::beg );
cout << inGameFile.tellg() << endl; // result is -1 again!

Every attempt at i/o will fail until the stream state
is reset (e.g. with 'clear()'.
// Does not work this way; try to close and reopen:
inGameFile.close();
if ( !inGameFile)
{
cerr << "Failed to close(3).\n";
//exit(1);
}

inGameFile.open( "scores.txt", ios::in );
if ( !inGameFile)
{
cerr << "Failed to open(4).\n";
//exit(1);
} inGameFile.open( "scores.txt", ios::in );

}

I think the 'cleaner' way is to close and reopen
rather than use 'seekg()'.
############################

The output is:

A total of 1363 games played.
No longer open(2).
-1
-1
Failed to close(3).
Failed to open(4).

############################

Compiler is c++ (GCC) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)

I did something similar on gnu c++ 2.95 under windows, where I could
resolve it by closing and reopening the file. This time it does not
work.

It seems that my inGameFile is automatically closed

No it is not. It will not be closed until you either
explicitly call 'close()', or the stream object goes
out of scope.
when I read the
last line, and I can neither move the get pointer nor re-open the
file.

You can't do *anything* until you reset the stream state.
Can someone explain me how can I overcome this?

See above.

-Mike
 
R

Rob Williscroft

Sanyi wrote in
// count the number of games
int nGames = 0;
while ( inGameFile.getline(stLine, LINE) )
{
nGames++;
}

When this loop exits the stream is in an "fail" state as the last
operation .getline(...) failed, you need to clear this error
before proceding:

inGameFile.clear();

You might also want to check that the op "failed" for the right
reason first, ie EOF was encounterd:

// the loop exited why?
if ( !inGameFile.eof() )
{
cerr << "read of game file failed\n";
exit( 0 );
}

// Ok to clear EOF was expected:
inGameFile.clear();


cout << "A total of " << nGames << " games played.\n";
// Everything works fine this far

if ( !inGameFile)
{
cerr << "No longer open(2).\n"; // inGameFile no longer defined!
//exit(1);
}

HTH

Rob.
 
M

Mohamed Ghouse

I think the 'cleaner' way is to close and reopen
rather than use 'seekg()'.

I don't understand the reason for not using seekg() function. Closing &
re-opening a file is more expensive operation than setting the seek pointer.
Setting a pointer is normally not an unclean operation.
 
M

Mike Wahler

Mohamed Ghouse said:
I don't understand the reason for not using seekg() function. Closing &
re-opening a file is more expensive operation than setting the seek
pointer.

You cannot know that for sure, this depends upon
the host platform. The "traditional wisdom" is
to not worry about performance while writing the
code, but only after its been *proven* (via testing
and profiling) to be an issue.
Setting a pointer is normally not an unclean operation.

I meant 'clean' from a source code perspective.
Of course this is only my opinion. Using "seek"
operation isn't technically "right" or "wrong".

-Mike
 
W

WW

Mike said:
I think the 'cleaner' way is to close and reopen
rather than use 'seekg()'.

Except for platforms where closing the last file on a media enables the
media to be ejected, and if there is a waiting eject request it will be
ejected. So I say if you want to read the file from the beginning go to the
beginning and read it. If you want to close it, close it. Just like I do
not buy a book again because I want to read it again. :) But this is only
my experience and opinion.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,143
Messages
2,570,822
Members
47,368
Latest member
michaelsmithh

Latest Threads

Top