fstream ?

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

    #1

    fstream ?


    Before I resort to the "fopen" family, can some-one please direct me to a
    tutorial on the net about the "fstream" family.

    I've gone through about 10 references and they're all complete bullshit. I'm
    trying to find simple answers to simple questions.

    What exactly does the constructor do? How does the whole eof thing work?


    -JKop
  • Nicolas Pavlidis

    #2
    Re: fstream ?

    JKop <NULL@NULL.NULL > writes:
    [color=blue]
    > Before I resort to the "fopen" family, can some-one please direct me to a
    > tutorial on the net about the "fstream" family.[/color]

    Not a tutorial but a reference, maybe it helps:

    [color=blue]
    > I've gone through about 10 references and they're all complete bullshit. I'm
    > trying to find simple answers to simple questions.
    >
    > What exactly does the constructor do? How does the whole eof thing work?[/color]

    See the reference.

    HTH && Kind regrads,
    Nicolas

    --
    | Nicolas Pavlidis | Elvis Presly: |\ |__ |
    | Student of SE & KM | "Into the goto" | \|__| |
    | pavnic@sbox.tug raz.at | ICQ #320057056 | |
    |-------------------University of Technology, Graz----------------|

    Comment

    • JKop

      #3
      Re: fstream ?

      [color=blue]
      > http://www.cppreference.com/cppio.html[/color]


      Thanks, but that's right at the top of my "bullshit" list.


      -JKop

      Comment

      • Fraser Ross

        #4
        Re: fstream ?

        The eof flag is set after an attempt to read past the end. It won't be set
        after opening a file of size 0.

        Fraser.


        "JKop"[color=blue]
        >
        > Before I resort to the "fopen" family, can some-one please direct me to a
        > tutorial on the net about the "fstream" family.
        >
        > I've gone through about 10 references and they're all complete bullshit.[/color]
        I'm[color=blue]
        > trying to find simple answers to simple questions.
        >
        > What exactly does the constructor do? How does the whole eof thing work?
        >
        >
        > -JKop[/color]


        Comment

        • Karl Heinz Buchegger

          #5
          Re: fstream ?

          JKop wrote:[color=blue]
          >
          > Before I resort to the "fopen" family, can some-one please direct me to a
          > tutorial on the net about the "fstream" family.
          >
          > I've gone through about 10 references and they're all complete bullshit. I'm
          > trying to find simple answers to simple questions.[/color]

          And the simple answers are:
          The 'fstream' family works exactly like the 2 objects you already are
          familiar with: cin, cout

          The only difference is: cin and cout are predefined objects, while you
          have to create the file-stream objects on your own.
          [color=blue]
          >
          > What exactly does the constructor do?[/color]

          Creating the stream object. Depending on which constructor you use exactly,
          the constructor may also open the file and connect the stream with it. The
          stream is then immediatly ready to be read from or write to.

          [color=blue]
          > How does the whole eof thing work?[/color]

          eof() works different in C or C++, then it does in a lot of other
          languages. In C or C++ the runtime system does not try to tell the
          future. As a consequence, eof returns true only if you try *and* failed
          to read past the end of the stream.
          So eof() is typically used to figure out, why a previous read operation
          has failed. If it was because eof() then everything is ok, the file
          could have been read correctly till the end.

          As an example, study this code snippet, which
          reads a text file line by line and copies the
          read line into a new file (just to do something
          with the data)

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

          using namespace std;

          int main()
          {
          ifstream InFile( "C:\\test.d at" ); // ifstream: input file stream
          ofstream OutFile( "C:\\Copy.d at" ); // ofstream: output file stream

          if( !InFile.is_open () ) {
          cout << "Could not open input file" << endl;
          return EXIT_FAILURE;
          }

          if( !OutFile.is_ope n() ) {
          cout << "Could not open output file" << endl;
          return EXIT_FAILURE;
          }

          string InLine;

          while( getline( InFile, InLine ) )
          OutFile << InLine;

          if( !InFile.eof() )
          cout << "Error during read from file" << endl;
          }

          Note also the typical read loop:

          while( data_can_be_rea d ) {
          process data
          }

          // figure out why the loop terminated.
          // if it was because eof, everything is fine
          if( !eof() )
          Process error during read


          --
          Karl Heinz Buchegger
          kbuchegg@gascad .at

          Comment

          • John Harrison

            #6
            Re: fstream ?


            "Fraser Ross" <fraserATmember s.v21.co.united kingdom> wrote in message
            news:41597b96@n ews.greennet.ne t...[color=blue]
            > The eof flag is set after an attempt to read past the end. It won't be[/color]
            set[color=blue]
            > after opening a file of size 0.
            >
            > Fraser.
            >[/color]

            int i;
            file >> i;

            This may successfully read an integer AND set the end of file. If the
            integer is the very last thing in the file then the end of file will be set
            because you have to read past the end of file to determine that the integer
            has been fully read. But if there is a space after the last integer then
            reading that space will tell you that the integer has been fully read and
            end of file will not be set.

            Same applies to getline and other similar read functions that have to read
            to some terminator.

            John


            Comment

            • JKop

              #7
              Re: fstream ?


              Thanks Karl.

              Here's the gist of what I'm trying to do at the moment: Let's say I have a
              file "mammals.tx t" and it contains:

              cat
              dog
              ape
              monkey
              horse
              pig

              What I want to do is remove a certain line, let's say "horse", so that after
              the program runs, "mammals.tx t" will look like so:

              cat
              dog
              ape
              monkey
              pig

              Here's what I'm doing so far:

              std::ifstream mammal_file( "mammal.txt " );

              if ( !mammal_file.is _open() )
              {
              std::cout << "ERROR: Unable to open \"mammal.txt\"\ n";
              throw AnException();
              }

              //The file is now open
              std::string one_line;


              What I'm intending to do is copy all the lines into a new *output* file
              stream, except "horse", and then overwrite the original. Would you be able
              to provide any tips at all please?


              -JKop

              Comment

              • Karl Heinz Buchegger

                #8
                Re: fstream ?

                JKop wrote:[color=blue]
                >
                >
                > What I'm intending to do is copy all the lines into a new *output* file
                > stream, except "horse", and then overwrite the original. Would you be able
                > to provide any tips at all please?[/color]

                Sure.

                You are on the right track. When dealing with text files (except in some
                rare circumstances), then the only possible way to modify that file is
                be writing a new one and while writing that file apply all the intended
                modifications. The only exception is when the replacement takes up the
                same amount of bytes as the original, then you can simply seek to the
                position and overwrite. But those cases are rare.

                The next thing you should think about is:
                How do I read. I mean: Which functionality do I use.
                In your case you have 2 choices

                you could eg.

                std::string InWord;
                InFile >> InWord;

                This will work in your case, since each line contains only a single word.
                So the basic loop would look like this

                ...
                while( mammal_file >> InWord ) {
                if( InWord != "horse" )
                OutFile << InWord << "\n";
                }
                ...

                But I often feel that a different approach is simpler. What is
                the problem? The problem comes if the file format gets more complicated,
                saying you have 3 words on each line and there have to be exactly 3 words
                on each line or otherwise the record (the line) is in error. So how to do this?
                In cases like this it is often simpler to use getline (as I did in the
                previous post). You use getline to read in the whole line as a single string
                and then use eg. string functions to seperate that total string into the
                words. Or you could use a stringstream to do the same.
                So why is that often simpler. Think of the error case. By using getline
                you have read the whole record, so if you figure out that that record
                is bogous you don't need to do anything special with the input stream. You
                just don't do anything with the bogus record and continue reading (and
                emit an error message).
                But in the read loop using >>?
                Well, first of all you need to detect that the line is in error. >> ignores
                line breaks because they are considered as white space. So detecting that
                the number of words per line is wrong isn't that simple. Even then, lets say
                the file format asks for a number, but in the file there is a text string "abc".[color=blue][color=green]
                >> will fail for obvious reasons. But what then? In order to continue you still[/color][/color]
                need to read until the end of that record is read (the line break) for finding
                the start of the next record. With the getline-version this is done all automatically.

                But there is one (minor) point with getline. getline reads *and* includes the terminator
                (in this case '\n'). So often one needs to get rid of that terminator are at least
                deal with it. In your specific case, that would eg. be

                while( getline( mammal_file, one_line ) ) {
                if( one_line != "horse\n" )
                OutFile << one_line;
                }

                Note: In the version using >> I had to write a '\n' on my own to the output stream, because[color=blue][color=green]
                >> has filtered it away. In the getline version I don't have to do that, because getline[/color][/color]
                has placed a '\n' in one_line as last character. That is: if there was one in the file.
                The last line in the file may or may not contain a terminating '\n'.

                So much for the thoughts about how to get at the file content.
                Back to your program.
                Open the output file and write to it whatever loop you want to choose.
                Once you have finished, all that is left is

                * delete the original file
                you will want to use function remove() from <cstdio> for that
                * rename the newly created file to the original file name
                you will want to use function rename() from <cstdio> for that

                It is a good idea to actually close the streams before the deletion and
                renaming takes place.

                As for: How to name that temporary file.
                Often just a variation of the input file name is used. If the file system
                supports file extensions, then it is often the name of the input file with
                a different extension. But there is a second solution. As a leftover from
                C there is a function called tmpnam, which generates a filename to be guaranteed
                to not collide with any other file name in the directory. But look up the documentation
                for that function. Often there are some tricky interactions with environment variables.

                --
                Karl Heinz Buchegger
                kbuchegg@gascad .at

                Comment

                • JKop

                  #9
                  Re: fstream ?


                  Here's how it's going so far:

                  #include <fstream>
                  #include <string>

                  int main()
                  {
                  std::ifstream mammals_file( "mammals.tx t" );

                  if ( !mammals_file.i s_open() )
                  {
                  std::cout << "ERROR: Unable to open \"mammals.txt\" \n";
                  return -1;
                  }

                  //The file is now open

                  {
                  std::ofstream out_file;

                  std::string one_line;

                  do
                  {
                  std::getline(ma mmals_file, one_line);

                  if ( !CompareWithout RegardToCaseX( "horse", one_line.c_str( ) )
                  ) out_file << one_line << '\n'; //Should I have that '\n' there?
                  }
                  while ( !mammals_file.e of() );

                  //Now save the file, overwriting the original, but how . . . ?
                  }
                  }


                  Any thoughts?


                  -JKop

                  Comment

                  • JKop

                    #10
                    Re: fstream ?


                    Thanks.

                    I'd written a reply and then two seconds later I wrote another
                    [color=blue]
                    > * delete the original file
                    > you will want to use function remove() from <cstdio> for that
                    > * rename the newly created file to the original file name
                    > you will want to use function rename() from <cstdio> for that[/color]

                    I was wondering if I'd have to name the file in the first place? Is there
                    anyway to just have it reside in memory, and then at my discretion save it
                    as a file?

                    One thing also, I'll have to use "getline" because there could be spaces on
                    the lines in these files.


                    -JKop

                    Comment

                    • Karl Heinz Buchegger

                      #11
                      Re: fstream ?

                      JKop wrote:[color=blue]
                      >
                      > Here's how it's going so far:
                      >
                      > #include <fstream>
                      > #include <string>
                      >
                      > int main()
                      > {
                      > std::ifstream mammals_file( "mammals.tx t" );
                      >
                      > if ( !mammals_file.i s_open() )
                      > {
                      > std::cout << "ERROR: Unable to open \"mammals.txt\" \n";
                      > return -1;
                      > }
                      >
                      > //The file is now open
                      >
                      > {
                      > std::ofstream out_file;
                      >[/color]

                      You want to pass a file name to the ofstream constructor, such that it
                      opens the file for you.
                      [color=blue]
                      > std::string one_line;
                      >
                      > do
                      > {
                      > std::getline(ma mmals_file, one_line);
                      >
                      > if ( !CompareWithout RegardToCaseX( "horse", one_line.c_str( ) )
                      > ) out_file << one_line << '\n'; //Should I have that '\n' there?[/color]

                      You used getline. So getline will include the terminator '\n' in the read
                      string. There is however one potential pitfall, the last line in the file
                      may not be terminated with '\n', thus the string will not contain it.

                      Best is often: read with getline, and look at the last character in the string.
                      If it is a '\n', discard it.

                      [color=blue]
                      > }
                      > while ( !mammals_file.e of() );
                      >
                      > //Now save the file, overwriting the original, but how . . . ?[/color]

                      delete original file with remove()
                      rename written file to original file name using rename()


                      out_file << one_line[color=blue]
                      > }
                      > }
                      >
                      > Any thoughts?
                      >
                      > -JKop[/color]


                      --
                      Karl Heinz Buchegger
                      kbuchegg@gascad .at

                      Comment

                      • Karl Heinz Buchegger

                        #12
                        Re: fstream ?

                        JKop wrote:[color=blue]
                        >
                        > Thanks.
                        >
                        > I'd written a reply and then two seconds later I wrote another
                        >[color=green]
                        > > * delete the original file
                        > > you will want to use function remove() from <cstdio> for that
                        > > * rename the newly created file to the original file name
                        > > you will want to use function rename() from <cstdio> for that[/color]
                        >
                        > I was wondering if I'd have to name the file in the first place? Is there
                        > anyway to just have it reside in memory, and then at my discretion save it
                        > as a file?[/color]

                        std::vector<std ::string> will happily store all the strings until
                        you are ready to

                        * close the original file
                        * open the same file for output (which will automatically truncate it
                        to 0 size)
                        * write the vector content to it

                        But note: In a high secure environment that would not be acceptable.
                        During the time period of opening the file for writing and the actual
                        finishing of writing, the data exist in memory only. If the computer
                        crashes during that time (eg. power outage) the data is lost forever.

                        Using the other version of writing to a temporary and then deleting/renaming
                        ensures that there is always one complete copy of the whole data set on
                        the hard disk.
                        [color=blue]
                        >
                        > One thing also, I'll have to use "getline" because there could be spaces on
                        > the lines in these files.[/color]

                        Oh. I wanted to mention this, but somehow I forgot :-)
                        [color=blue]
                        >
                        > -JKop[/color]


                        --
                        Karl Heinz Buchegger
                        kbuchegg@gascad .at

                        Comment

                        • Howard

                          #13
                          Re: fstream ?


                          "Karl Heinz Buchegger" <kbuchegg@gasca d.at> wrote in message
                          news:415BF88E.F 62E6072@gascad. at...[color=blue]
                          >
                          > Best is often: read with getline, and look at the last character in the[/color]
                          string.[color=blue]
                          > If it is a '\n', discard it.
                          >[/color]

                          I've got a question on comparing a char against '\n'. Since on some
                          systems, '\n' is represented by #13#10 (a CR/LF pair), what happens when you
                          compare a char with it? Is there some internal mechanism that actually
                          compares two bytes instead of just one?

                          -Howard


                          Comment

                          • Ron Natalie

                            #14
                            Re: fstream ?


                            "Howard" <alicebt@hotmai l.com> wrote in message news:d0X6d.4609 30$OB3.267267@b gtnsc05-[color=blue]
                            >
                            > I've got a question on comparing a char against '\n'. Since on some
                            > systems, '\n' is represented by #13#10 (a CR/LF pair), what happens when you
                            > compare a char with it? Is there some internal mechanism that actually
                            > compares two bytes instead of just one?
                            >[/color]
                            '\n' is ALWAYS a single character. ALWAYS.

                            The only thing that happens is that under certain circumstances an output
                            operation may output two characters when an single '\n' character is
                            fed to it (and similarly on input).

                            Comment

                            • Howard

                              #15
                              Re: fstream ?


                              "Ron Natalie" <ron@sensor.com > wrote in message
                              news:415c442f$0 $27746$9a6e19ea @news.newshosti ng.com...[color=blue]
                              >
                              > "Howard" <alicebt@hotmai l.com> wrote in message[/color]
                              news:d0X6d.4609 30$OB3.267267@b gtnsc05-[color=blue][color=green]
                              > >
                              > > I've got a question on comparing a char against '\n'. Since on some
                              > > systems, '\n' is represented by #13#10 (a CR/LF pair), what happens when[/color][/color]
                              you[color=blue][color=green]
                              > > compare a char with it? Is there some internal mechanism that actually
                              > > compares two bytes instead of just one?
                              > >[/color]
                              > '\n' is ALWAYS a single character. ALWAYS.
                              >
                              > The only thing that happens is that under certain circumstances an output
                              > operation may output two characters when an single '\n' character is
                              > fed to it (and similarly on input).
                              >[/color]

                              Ah, that makes sense. Thanks.
                              -Howard


                              Comment

                              Working...