Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » fstream behavior

This thread is locked; no one can reply to it. rss feed Print
fstream behavior
Steve Terry
Member #1,989
March 2002
avatar

I can't understand why fstream sets the failbits when the file you try to open does not exist. I ran into a strange problem today related to fstream in that if the failbit is set it's easy to run into an infinite loop:

1fstream fin;
2fin.open("C:\some_file_that_does_not_exist.txt");
3if(!fin.is_open())
4{
5 fin.open("C:\some_file_that_exists.txt");
6}
7 
8if(fin.is_open())
9{
10 string tmp;
11 while(!getline(fin, tmp).eof())
12 {
13 // Infinite loop!
14 }
15}

The problem is that the first fin.open failed which set the failbit while the second fin.open succeeded but did not reset the failbits. When you call getline it will never be able to read and therefore never hit the eof.

Simple fix is to add fin.clear() before getline but it's not evident by the logic above that you must do that. Shouldn't fstream reset the failbits if open succeeds?

___________________________________
[ Facebook ]
Microsoft is not the Borg collective. The Borg collective has got proper networking. - planetspace.de
Bill Gates is in fact Shawn Hargreaves' ßî+çh. - Gideon Weems

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

I use a different check to see if the fstream is valid. Instead of using fstream.is_open() , I use either a boolean test with operator ! or a call to the fstream.good() function.

1ofstream log_file(".\\program_log.txt");
2 
3// boolean
4if (!log_file) {// couldn't open log properly , operator ! does same thing as ios::fail()
5 // decide whether to continue without log
6}
7// good() method
8if (!(log_file.good())) {
9 // see what the problem with the file is
10 if (log_file.fail()) {// if fail() returns true then either failbit set or badbit set
11 if (!log_file.bad()) {
12 // fail bit set for log file
13 /// Try clearing state and repositioning stream
14 log_file.clear();
15 log_file.seekg(0 , ios::beg);
16 log_file.seekp(0 , ios::beg);
17 } else {
18 // bad bit set for log file , and perhaps fail bit also
19 // bad bit means inoperable as far as I know , so quit
20 }
21
22 } else {// if good() is false and if fail() is false , then eof() should be true
23 // just need to stop reading or reposition place in stream
24 // have to call clear to get rid of the eofbit state though
25 log_file.clear();
26 log_file.seekg(0 , ios::beg);
27 }
28}

It makes sense that if you open a new fstream that the failbit shouldn't be set since it hasn't actually failed , I think you're right about that.

- Append -
Actually , though , I understand why the failbit is set when opening a file doesn't work. You wouldn't want ios::good() to return true when a file failed to open would you? So I suppose it's their reasoning that the failbit should be cleared manually by the user but I still agree that if open is called , it should reset the bits itself. Assuming that they would use the ios::setstate function to set the state of the stream after attempting to open a file , then it would make sense that they would use ios::setstate(goodbit) if successful , but maybe they don't. Should be easy to test with something like :

bool file_error_flag = false;
fstream file;
file.open(".\\nonexistentfile.txt");
if (file.good()) {
  cout << "File stream incorrectly reported as good when opening a non existent file" << endl;
} else {
  file_error_flag = true;
}
file.open(".\\realfile.txt");
if (file_error_flag) {
  if (!file.good()) {
    cout << "File stream incorrectly reported as not good() when opening an actual file" << endl;
  }
}

Arthur Kalliokoski
Second in Command
February 2005
avatar

Quote:

Simple fix is to add fin.clear() before getline but it's not evident by the logic above that you must do that. Shouldn't fstream reset the failbits if open succeeds?

It might be considered a "sticky bit" that you must explicitly clear. Then you could detect errors indefinitely later, like glError() or fxam do.

[EDIT] glError() clears them as you fetch the errors.

They all watch too much MSNBC... they get ideas.

Karadoc ~~
Member #2,749
September 2002
avatar

Edgar Reynaldo said:

Actually , though , I understand why the failbit is set when opening a file doesn't work. You wouldn't want ios::good() to return true when a file failed to open would you?

I agree that the failbit should be set when open() fails. But I think what Steve Terry is saying is that when the second open() succeeds it should unset the failbit. It is a new file, essentially a new instance of the whole fstream thing, and nothing has gone wrong yet - so the failbit should have been unset.

-----------

Go to: