ifstream problems

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • hall

    ifstream problems

    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


    --
    <- remove capital x:s from e-mail to reply ->

  • Rob Williscroft

    #2
    Re: ifstream problems

    hall wrote in news:iyfic.5703 0$mU6.234767@ne wsb.telia.net in comp.lang.c++:
    [color=blue]
    > 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";}[/color]

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

    if ( in.is_open() )
    [color=blue]
    > in.close(); if(!in) {cout << "error\n";}[/color]

    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.
    [color=blue]
    >
    > 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?
    >[/color]

    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.
    --

    Comment

    • hall

      #3
      Re: ifstream problems

      Rob Williscroft wrote:[color=blue]
      > hall wrote in news:iyfic.5703 0$mU6.234767@ne wsb.telia.net in comp.lang.c++:
      >
      >[color=green]
      >>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";}[/color]
      >
      >
      > You could prevent this from puting "in" into an error state with:
      >
      > if ( in.is_open() )
      >
      >[color=green]
      >> in.close(); if(!in) {cout << "error\n";}[/color]
      >
      >
      > but a second call to close() isn't the only way "in" can become bad.[/color]

      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::strin g 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.
      [color=blue]
      >
      > Also { in.close(); in.clear(); } is probably less expensive and
      > more Bullet Proof(tm) anyway.
      >[/color]

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

      void open(){ in.clear(std::s tring 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.

      [color=blue]
      >
      > 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.
      >[/color]

      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.
      [color=blue]
      > 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;
      > }
      >[/color]

      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.flus h(); in.clear(); in.close()};
      to make sure that the file is actually closed?
      [color=blue]
      > Rob.[/color]

      regards
      /hall
      --
      <- remove capital x:s from e-mail to reply ->

      Comment

      • Rob Williscroft

        #4
        Re: ifstream problems

        hall wrote in news:p0iic.5704 3$mU6.234221@ne wsb.telia.net in
        comp.lang.c++:
        [color=blue]
        > Rob Williscroft wrote:[color=green]
        >> hall wrote in news:iyfic.5703 0$mU6.234767@ne wsb.telia.net in
        >> comp.lang.c++:
        >>
        >>[color=darkred]
        > >>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";}[/color]
        >>
        >>
        >> You could prevent this from puting "in" into an error state with:
        >>
        >> if ( in.is_open() )
        >>
        >>[color=darkred]
        >>> in.close(); if(!in) {cout << "error\n";}[/color]
        >>
        >>
        >> but a second call to close() isn't the only way "in" can become bad.[/color]
        >
        > 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::strin g 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.
        >[color=green]
        > >
        > > Also { in.close(); in.clear(); } is probably less expensive and
        > > more Bullet Proof(tm) anyway.
        > >[/color]
        >
        > Would this then all be solved by changing the open() method into
        >
        > void open(){ in.clear(std::s tring s); in.open(s)}[/color]

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

        It doesn't close the file, and open will fail, if the ifstream is
        already open.
        [color=blue]
        >
        > 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.
        >[/color]

        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][color=blue][color=green]
        >>
        >> The above code reuses 'in' (well its storage anyway) without
        >> all the faffing about, it lets the compiler do it instead.
        > >[/color]
        >
        > 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.
        >[color=green]
        >> 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;
        >> }
        >>[/color]
        >
        > 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[/color]

        Yes according to the standard, you can (I just checked)
        [color=blue]
        > void close(){in.flus h(); in.clear(); in.close()};
        > to make sure that the file is actually closed?
        >[/color]

        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::open( std::strinf const &s )
        {
        close(); /* InFile:: */
        in.open( s.c_str() );
        return in.good();
        }

        Rob.
        --

        Comment

        • hall

          #5
          Re: ifstream problems


          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

          --
          <- remove capital x:s from e-mail to reply ->

          Comment

          Working...