ifstream problems

H

hall

Hi.

I ran across a bug in one of my problems and after spending some time
tracking it down i found that the problem arose in a piece of code that
essentially did this:

-----------
ifstream in("in.txt"); if(!in) {cout << "error\n";}
in.close(); if(!in) {cout << "error\n";}
in.close(); if(!in) {cout << "error\n";}

in.open("in.txt"); if(!in) {cout << "error\n";}
------------
It reports that opening the file on the last line was unsuccessful as
the last operation, the second in.close() causes an ifstream error.

After digging around in Stroustrups TC++PL i found that putting
'in.clear();' before the in.open() on the last line alleviates this
problem, but is this the right way of refreshing an ifstream that has
had a problem, or may I cause other problems by doing it in this way? Is
there another way I should do it?

regards
/hall
 
R

Rob Williscroft

hall wrote in in comp.lang.c++:
Hi.

I ran across a bug in one of my problems and after spending some time
tracking it down i found that the problem arose in a piece of code that
essentially did this:

You could prevent this from puting "in" into an error state with:

if ( in.is_open() )
in.close(); if(!in) {cout << "error\n";}

but a second call to close() isn't the only way "in" can become bad.

Also { in.close(); in.clear(); } is probably less expensive and
more Bullet Proof(tm) anyway.
in.open("in.txt"); if(!in) {cout << "error\n";}
------------
It reports that opening the file on the last line was unsuccessful as
the last operation, the second in.close() causes an ifstream error.

After digging around in Stroustrups TC++PL i found that putting
'in.clear();' before the in.open() on the last line alleviates this
problem, but is this the right way of refreshing an ifstream that has
had a problem, or may I cause other problems by doing it in this way?
Is there another way I should do it?

You should consider (if applicable):

int main()
{
// first:
{
ifstream in( "in.txt" );
// whatever
}

// second:
{
ifstream in( "in.txt" );
// different whatever

}
}

The above code reuses 'in' (well its storage anyway) without
all the faffing about, it lets the compiler do it instead.

In theory, your original method may be faster, but the real
cost is probably opening and closing the file, so it unlikly
that the difference can be measured.

If the above isn't applicable (and you can't make it so):

std::ifstream &reopen( std::ifstream &ifs, char const *name )
{
ifs.clear();

ifs.close();
ifs.clear();

ifs.open( name );

return ifs;
}

Rob.
 
H

hall

Rob said:
hall wrote in in comp.lang.c++:




You could prevent this from puting "in" into an error state with:

if ( in.is_open() )




but a second call to close() isn't the only way "in" can become bad.

I am aware of this, and while I can prevent "in" from being closed twise
easily (as it is in a class for formatted output of data) I was more
worried of other causes that may make the ifstream turn bad, such as end
of file.

The class look something like (not tested code)

class Infile {
private:
std::ifstream in;
// ...
public:
void open(std::string s){ in.open(s) };
void close() { in.flush(); in.close() };
// ... methods for reading from file
};

As it is now, opening the ifstream may fail if a user previously have
made something to make the ifstream object to go bad, such as reading
untill end of file, trying to open a nonexisting file and so on.
Also { in.close(); in.clear(); } is probably less expensive and
more Bullet Proof(tm) anyway.

Would this then all be solved by changing the open() method into

void open(){ in.clear(std::string s); in.open(s)}

without giving any unpleasant suprises that i am not aware of (such as
that clear() doesn't fix the ifstream for all bad states)?

My only other idea for solving this was by turning "in" into an ifstream
pointer and create an instance in open() and delete it in close(), but i
thought it would just be too ugly and a better way must exist.

You should consider (if applicable):

int main()
{
// first:
{
ifstream in( "in.txt" );
// whatever
}

// second:
{
ifstream in( "in.txt" );
// different whatever

}
}

The above code reuses 'in' (well its storage anyway) without
all the faffing about, it lets the compiler do it instead.

This, the reusal of storage, i did not know. I'll keep it in mind for
the future, but for this class its not a good idea as i think it is to
be begging for errors to require anyone who uses the code to put each
Infile object in different scopes if he wants to reuse the object.
In theory, your original method may be faster, but the real
cost is probably opening and closing the file, so it unlikly
that the difference can be measured.

If the above isn't applicable (and you can't make it so):

std::ifstream &reopen( std::ifstream &ifs, char const *name )
{
ifs.clear();

ifs.close();
ifs.clear();

ifs.open( name );

return ifs;
}

Now this raises a question. Can I not close a file if
ifstream::good()=false ? Should I also change the close() function in my
class into
void close(){in.flush(); in.clear(); in.close()};
to make sure that the file is actually closed?

regards
/hall
 
R

Rob Williscroft

hall wrote in in
comp.lang.c++:
I am aware of this, and while I can prevent "in" from being closed
twise easily (as it is in a class for formatted output of data) I was
more worried of other causes that may make the ifstream turn bad, such
as end of file.

The class look something like (not tested code)

class Infile {
private:
std::ifstream in;
// ...
public:
void open(std::string s){ in.open(s) };
void close() { in.flush(); in.close() };
// ... methods for reading from file
};

As it is now, opening the ifstream may fail if a user previously have
made something to make the ifstream object to go bad, such as reading
untill end of file, trying to open a nonexisting file and so on.


Would this then all be solved by changing the open() method into

void open(){ in.clear(std::string s); in.open(s)}

see below
without giving any unpleasant suprises that i am not aware of (such as
that clear() doesn't fix the ifstream for all bad states)?

It doesn't close the file, and open will fail, if the ifstream is
already open.
My only other idea for solving this was by turning "in" into an
ifstream pointer and create an instance in open() and delete it in
close(), but i thought it would just be too ugly and a better way must
exist.

Ugly dosn't matter, but that you then have to manage the liftime
of the new'd ifstream does, so in this case I'd go with the
close(), clear(), open() method.

[snip]
This, the reusal of storage, i did not know. I'll keep it in mind for
the future, but for this class its not a good idea as i think it is to
be begging for errors to require anyone who uses the code to put each
Infile object in different scopes if he wants to reuse the object.


Now this raises a question. Can I not close a file if
ifstream::good()=false ? Should I also change the close() function in
my class into

Yes according to the standard, you can (I just checked)
void close(){in.flush(); in.clear(); in.close()};
to make sure that the file is actually closed?

The flush() isn't needed, close() if indeed the ifstream is open
will do that for you:

void InFile::close()
{
in.close();
in.clear();
}

bool InFile::eek:pen( std::strinf const &s )
{
close(); /* InFile:: */
in.open( s.c_str() );
return in.good();
}

Rob.
 
H

hall

Thanks for your input!


and also, thanks for seeing through the misstakes I made while writing
the code examples. Guess I was a bit to tired last night ;-)

regards
/hall
 

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,166
Messages
2,570,907
Members
47,447
Latest member
TamiLai26

Latest Threads

Top