[C++] Rewinding an isteam and GNU G++

  • Thread starter Thomas Matthews
  • Start date
T

Thomas Matthews

Hi,

I've searched the FAQ and no tips on this one.
Searching the newsgroups shows that the proper
method for rewinding an istream is:
istream inp;
// read past EOF.
inp.clear(); // Clear the stream state
inp.seekg(0);

I've used the above technique with Borland
C++ Builder and it works. However, it doesn't
work with GNU g++ 3.3.1 (cygwin special).
Here is a small demo program (annotated):

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

using namespace std; // for this example.

int main(void)
{
ifstream inp("my_data.txt");
string text_line;

// Read the entire data file
// and send to cout.
while (getline(inp, text_line))
{
cout << text_line << endl;
}

// Now, the inp file is in an error
// state, so clear it before positioning.
inp.clear();

// At this point, G++ reports that inp is
// in a good state {inp.good() == true}.

// Rewind the file.
inp.seekg(0);

// At this point, G++ reports that inp is
// in a failed state (inp.fail() == true).
// However, Borland compiler reports that
// inp is in a good state.

// Clear the state after rewinding.
// This is primarily for G++.
inp.clear();

// Read {the first} line of text.
if (getline(inp, text_line))
{
cout << text_line << endl;
}
else
{
// The G++ compiler always comes here.
cerr << "getline after rewind failed." << endl;
}

return EXIT_SUCCESS;
}

So, what is the standard method for rewinding?
Which compiler is correct?
Can somebody test with Microsoft?

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book
http://www.sgi.com/tech/stl -- Standard Template Library
 
J

John Harrison

Thomas Matthews said:
Hi,


So, what is the standard method for rewinding?

That is.
Which compiler is correct?
Borland.

Can somebody test with Microsoft?

Works fine with Microsoft 7.1 (without the additional call to clear()). Also
works fine on g++ 3.3.3 (cygwin special)

Sounds like a g++ bug. I'd use a debugger to dig into the fstream/filebuf
code (or maybe you can just eyeball it) and find out exactly what is wrong.
Since it is only likely to need a header file change to fix it maybe you can
download the fix from somewhere. Seems unlikely that this sort of bug would
have gone unnoticed for long.

Or maybe you could just upgrade.

john
 
C

Chris \( Val \)

| Hi,
|
| I've searched the FAQ and no tips on this one.
| Searching the newsgroups shows that the proper
| method for rewinding an istream is:
| istream inp;
| // read past EOF.
| inp.clear(); // Clear the stream state
| inp.seekg(0);
|
| I've used the above technique with Borland
| C++ Builder and it works. However, it doesn't
| work with GNU g++ 3.3.1 (cygwin special).
| Here is a small demo program (annotated):

[snip]

| int main(void)
| {
| ifstream inp("my_data.txt");
| string text_line;
|
| // Read the entire data file
| // and send to cout.
| while (getline(inp, text_line))
| {
| cout << text_line << endl;
| }
|
| // Now, the inp file is in an error
| // state, so clear it before positioning.
| inp.clear();

Why not check for 'eof()' here ?

if( !inp.eof() )
// Handle error...

| // At this point, G++ reports that inp is
| // in a good state {inp.good() == true}.
|
| // Rewind the file.
| inp.seekg(0);
|
| // At this point, G++ reports that inp is
| // in a failed state (inp.fail() == true).
| // However, Borland compiler reports that
| // inp is in a good state.

If you cleared the flags, then the stream should
be in an good state, I would think.

Try this overload instead:
inp.seekg( 0, std::ios_base::beg );

Additionally, you can open the stream with the out
mode set as well:

std::ifstream inp( "my_data.txt", std::ios_base::eek:ut );

[snip]

| So, what is the standard method for rewinding?
| Which compiler is correct?
| Can somebody test with Microsoft?

I think Borland is correct, but I just thought of
something. Try to open the stream in binary mode
to get an accurate seek as well.

Cheers.
Chris Val
 
J

John Harrison

I think Borland is correct, but I just thought of
something. Try to open the stream in binary mode
to get an accurate seek as well.

It's valid to seek to the beginning of a file, even when the file is opened
in text mode.

john
 
A

Alwyn

Thomas Matthews said:
{
// The G++ compiler always comes here.
cerr << "getline after rewind failed." << endl;
}

return EXIT_SUCCESS;
}

It works for me.

$ cat rewind.cc
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>

using namespace std; // for this example.

int main(void)
{
ifstream inp("my_data.txt");
string text_line;

// Read the entire data file
// and send to cout.
while (getline(inp, text_line))
{
cout << text_line << endl;
}

// Now, the inp file is in an error
// state, so clear it before positioning.
inp.clear();

// At this point, G++ reports that inp is
// in a good state {inp.good() == true}.

// Rewind the file.
inp.seekg(0);

// At this point, G++ reports that inp is
// in a failed state (inp.fail() == true).
// However, Borland compiler reports that
// inp is in a good state.

// Clear the state after rewinding.
// This is primarily for G++.
inp.clear();

// Read {the first} line of text.
if (getline(inp, text_line))
{
cout << text_line << endl;
}
else
{
// The G++ compiler always comes here.
cerr << "getline after rewind failed." << endl;
}

return EXIT_SUCCESS;
}
$ g++ -v
Reading specs from /usr/libexec/gcc/darwin/ppc/3.3/specs
Thread model: posix
gcc version 3.3 20030304 (Apple Computer, Inc. build 1666)
$ g++ -g -o rewind rewind.cc
$ cat my_data.txt
Here are some lines
of text.
82-35-95-10:~/Scrap alwyn$ ./rewind
Here are some lines
of text.
Here are some lines


Alwyn
 
C

Chris \( Val \)

| >
| > I think Borland is correct, but I just thought of
| > something. Try to open the stream in binary mode
| > to get an accurate seek as well.

Hi John.

| It's valid to seek to the beginning of a file, even
| when the file is opened in text mode.

Yes, but I think you're missing the point I was trying
to make.

Try the following piece of code, with and without the
'binary' mode enabled, and see what the results are:

// Headers...

int main()
{
std::ifstream
InFile( "SomeFile.txt"/*, std::ios_base::binary*/ );

char Char( 0 );
std::size_t Size( 0 );

while( InFile.get( Char ) )
++Size;

std::cout << Size << std::endl;

return 0;
}

AFAIK, the binary flag accurately accounts for the new
line character '\n' as being the pair '\r\n'.

You will find that opening the file in binary mode, will
provide better accuracy for a seek - How many '\n's are
in a file ?

If using Windows for example, compare a file size(with this
flag and without it), against what windows tells you it is.

Cheers.
Chris Val
 
J

John Harrison

Chris ( Val ) said:
| >
| > I think Borland is correct, but I just thought of
| > something. Try to open the stream in binary mode
| > to get an accurate seek as well.

Hi John.

| It's valid to seek to the beginning of a file, even
| when the file is opened in text mode.

Yes, but I think you're missing the point I was trying
to make.

Try the following piece of code, with and without the
'binary' mode enabled, and see what the results are:

// Headers...

int main()
{
std::ifstream
InFile( "SomeFile.txt"/*, std::ios_base::binary*/ );

char Char( 0 );
std::size_t Size( 0 );

while( InFile.get( Char ) )
++Size;

std::cout << Size << std::endl;

return 0;
}

AFAIK, the binary flag accurately accounts for the new
line character '\n' as being the pair '\r\n'.

You will find that opening the file in binary mode, will
provide better accuracy for a seek - How many '\n's are
in a file ?

If using Windows for example, compare a file size(with this
flag and without it), against what windows tells you it is.

Cheers.
Chris Val

That's all well and good, but its got nothing to do with what the OP was
trying to do, namely seek to the beginning of a file. Something that is
perfectly valid in text or binary mode.

john
 
C

Chris \( Val \)

|
| | >
| > | > | >
| > | > I think Borland is correct, but I just thought of
| > | > something. Try to open the stream in binary mode
| > | > to get an accurate seek as well.
| >
| > Hi John.
| >
| > | It's valid to seek to the beginning of a file, even
| > | when the file is opened in text mode.

[snip example]

| That's all well and good, but its got nothing to do with what the OP was
| trying to do, namely seek to the beginning of a fi le.Somethingthatis
| perfectly valid in text or binary mode.

Yes, of course seeking is valid in text or binary mode :)

Cheers.
Chris Val
 
T

Thomas Matthews

Chris said:
| Hi,
|
| I've searched the FAQ and no tips on this one.
| Searching the newsgroups shows that the proper
| method for rewinding an istream is:
| istream inp;
| // read past EOF.
| inp.clear(); // Clear the stream state
| inp.seekg(0);
|
| I've used the above technique with Borland
| C++ Builder and it works. However, it doesn't
| work with GNU g++ 3.3.1 (cygwin special).
| Here is a small demo program (annotated):

[snip]

| int main(void)
| {
| ifstream inp("my_data.txt");
| string text_line;
|
| // Read the entire data file
| // and send to cout.
| while (getline(inp, text_line))
| {
| cout << text_line << endl;
| }
|
| // Now, the inp file is in an error
| // state, so clear it before positioning.
| inp.clear();

Why not check for 'eof()' here ?

if( !inp.eof() )
// Handle error...

| // At this point, G++ reports that inp is
| // in a good state {inp.good() == true}.
|
| // Rewind the file.
| inp.seekg(0);
|
| // At this point, G++ reports that inp is
| // in a failed state (inp.fail() == true).
| // However, Borland compiler reports that
| // inp is in a good state.

If you cleared the flags, then the stream should
be in an good state, I would think.

Try this overload instead:
inp.seekg( 0, std::ios_base::beg );

Additionally, you can open the stream with the out
mode set as well:

std::ifstream inp( "my_data.txt", std::ios_base::eek:ut );

[snip]

| So, what is the standard method for rewinding?
| Which compiler is correct?
| Can somebody test with Microsoft?

I think Borland is correct, but I just thought of
something. Try to open the stream in binary mode
to get an accurate seek as well.

Cheers.
Chris Val

Chris,

My objective is to rewind the file. I really don't care
if EOF has been hit or not.

For example, I read through the data file once for one text,
and I want to read through it again for another test.

The issue is that the rewind is not behaving correctly.


--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
T

Thomas Matthews

Thomas said:
Hi,

I've searched the FAQ and no tips on this one.
Searching the newsgroups shows that the proper
method for rewinding an istream is:
istream inp;
// read past EOF.
inp.clear(); // Clear the stream state
inp.seekg(0);

I've used the above technique with Borland
C++ Builder and it works. However, it doesn't
work with GNU g++ 3.3.1 (cygwin special).
Here is a small demo program (annotated):

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

using namespace std; // for this example.

int main(void)
{
ifstream inp("my_data.txt");
string text_line;

// Read the entire data file
// and send to cout.
while (getline(inp, text_line))
{
cout << text_line << endl;
}

// Now, the inp file is in an error
// state, so clear it before positioning.
inp.clear();

// At this point, G++ reports that inp is
// in a good state {inp.good() == true}.

// Rewind the file.
inp.seekg(0);

// At this point, G++ reports that inp is
// in a failed state (inp.fail() == true).
// However, Borland compiler reports that
// inp is in a good state.

// Clear the state after rewinding.
// This is primarily for G++.
inp.clear();

// Read {the first} line of text.
if (getline(inp, text_line))
{
cout << text_line << endl;
}
else
{
// The G++ compiler always comes here.
cerr << "getline after rewind failed." << endl;
}

return EXIT_SUCCESS;
}

So, what is the standard method for rewinding?
Which compiler is correct?
Can somebody test with Microsoft?

If the platform is of any concern, I am using Win95.


--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
M

Mike Wahler

Thomas Matthews said:
My objective is to rewind the file. I really don't care
if EOF has been hit or not.

For example, I read through the data file once for one text,
and I want to read through it again for another test.

The issue is that the rewind is not behaving correctly.

Well, a possible workaraound is to close and reopen
instead of seeking. Unless you're doing this many
many times, I doubt you'd notice a performance difference.

-Mike
 
B

B. v Ingen Schenau

Thomas said:
Hi,

I've searched the FAQ and no tips on this one.
Searching the newsgroups shows that the proper
method for rewinding an istream is:
istream inp;
// read past EOF.
inp.clear(); // Clear the stream state
inp.seekg(0);

I believe the correct method for rewinding is:

istream inp;
istream::pos_type beginning = inp.tellg();
// read past EOF
inp.clear();
inp.seekg(beginning);

It is possible that most implementations support the call inp.seekg(0),
but formally are the effects undefined.
istream::seekg(pos) calls, indirectly, basic_filebuff<>::seekpos(pos).
The standard states about basic_filebuf<>::seekpos():
"If sp is an invalid stream position, or if the function positions
neither sequence, the positioning operation fails. If sp has not been
obtained by a previous successful call to one of the positioning
functions (seekoff or seekpos) on the same file the effects are
undefined."
I've used the above technique with Borland
C++ Builder and it works. However, it doesn't
work with GNU g++ 3.3.1 (cygwin special).
Here is a small demo program (annotated):
So, what is the standard method for rewinding?
Which compiler is correct?

I think both are correct. :)
Can somebody test with Microsoft?

Bart v Ingen Schenau
 

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

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top