computer science - C++ Lesson 14:  fstreams - Text File I/O

INTRODUCTION:                 In this lesson you will learn about text file input and output using file streams.  The source programs you have been writing are all stored as text files.  After this lesson you will have a greater understanding of how files are saved and retrieved.

You have been using ofstreams to redirect your run output answers from the screen to disk.  Sending output to disk is relatively easy.  Reading text files from disk is a bit harder as we need to watch out for the EOF (end-of-file) sentinel value.  After this lesson, many of the programming exercises will work with data stored in text files.

 

The key topics for this lesson:

A.    Standard ASCII Text Files
B.    The fstream Objects
C.    Saving Text Files to Disk using ofstreams
D.    Reading Text Files from Disk using ifstreams
E.    Streams and Filters
 

VOCABULARY:                    

TEXT FILE                              EOF
EXTERNAL FILE                    INTERNAL FILE
ofstream                                    ifstream
FILTER

HandOut 14-1

DISCUSSION:                       

A.    Standard ASCII Text Files

1.    A text file is a sequential access file that stores characters.  A sequential file is one which must be read from the beginning of the file, and then element by element.  You must read the file from the beginning.  You cannot jump to any location in the file.

2.    A random access file is one where the program can access any element in the file, given its location in the file.  Random access files are available in C++, but they will not be covered in this curriculum guide.

3.    An ASCII text file is stored using the ASCII codes for each keystroke.  An 'a' is ASCII code 97, which is eventually stored in binary format (using ones and zeroes) on disk.

4.    A text file is organized by lines, just as a printed page would be.  Each line ends with a special character, the eoln (end-of-line) marker.  In C++ environments, the eoln marker corresponds to the return key and has an ASCII value of 10.

5.    The eof (end of file) marker marks the termination of a text file.  The eof marker is a unique hexadecimal value which can be checked for using various stream processing tools.

6.    A text file has as many eoln's (ASCII = 10) as there are lines in the file, but only one eof marker.

7.    A text file can store numeric data, but integer and float types are converted into text format.

8.    When a text file is stored on disk, it can be thought of as one long stream of ASCII codes.  The following text example on screen would be stored as one long list of ASCII codes on disk.

Apple

IBM

Disk text file:

65  112  112  108  101  10  73  66  77  "eof"

B.    The fstream Objects

1.    A stream is an abstraction referring to the flow of data from a source to a destination.  Up to this point in the course you have worked primarily with the iostreams called cin and cout.  These two objects work with data in the following directions 

                                Source                        Destination

       cin                    keyboard                        memory

       cout                   memory                         monitor

2.    C++ provides other stream objects which support other sources and/or destinations.  The location of these objects are:

       fstream.h                  file streams

       constrea.h                console output

       File streams will allow us to move information to and from secondary memory devices (disks).  Before we look at the syntax of fstreams we need to define some terms.

3.    External files exist in permanent form on some storage media, such as disks, diskettes, or tapes.  External files are also called physical files.

4.    An ifstream (i for input) object allows us to transfer data from an external file (disk) into memory.

5.    An ofstream (o for output) object allows us to send data from memory to an external file (disk).

6.    A linkage statement must occur which makes the fstream object an alias for a physical file.  The syntax of the open member function is described in section C.

7.    We will use the stream-insertion/extraction operators (<<, >>) to send data to and from disk.  The syntax of such statements is identical to that used with cin and cout. 

C.    Saving Text Files to Disk using ofstreams 

1.    An ofstream must be declared to allow a program to work with output to a text file.  This example is identical to the technique used to send the run output from labs to disk:

#include <fstream.h>

main ()

{

      //ofstream  outfile ("sample.txt", ios::out); -- the same as the two following lines

         ofstream   outfile;

         outfile.open ("sample.txt", ios::out);

         ...

}

 

2.    The fstream member function open needs two arguments, the name of the file and the file opening mode.  Here are the three most common file opening modes:

        ios::in           opens a file for input

       ios::out         opens a file for output

       ios::app        writes all output to the end of the file

(Metrowerks Code Warrior does not require the use of file opening modes.  Omit these from your open commands if you are programming in Metrowerks C++.)

3. In the above example, outfile, is an ofstream object which will be used with the stream-insertion operator (<<) to send data to an external file.

4. The declaration and initialization of outfile can be accomplished in one statement:

              ofstream  outfile ("sample.txt", ios::out);

       Of the two methods there are advantages for each approach.  The first method using 2 lines of code is more explicit and probably easier to read.  The second method saves a line of code and compresses the declaration and initialization of the ofstream object into one statement.  The curriculum guide will use the one line method most of the time.

5.    After the ofstream object has been linked to an external file, it is ready to use as a stream to send output to disk.  Here is a complete program to send text output to the current default disk.

Program 14-1

#include <fstream.h>

main ()

{

         ofstream   outfile;
         int  loop;
       
         outfile.open ("sample.txt", ios::out);

         for (loop = 1; loop <= 5; loop++)
                outfile << loop << "   Hello world" << endl;

         //  outfile.close();   not required, but shown for completion

         return 0;

} 

       The effect of the above program will create a text file called "sample.txt" on the default drive.  This file will look like this:

 

1   Hello world

2   Hello world

3   Hello world

4   Hello world

5   Hello world

 

       Notice that the integer value of loop is saved on disk in text format.

 

6.    C++ will automatically close file streams.  The member function outfile.close () was shown in the above program as a documentation statement.  You may omit this line from your text file processing programs.

 

D.    Reading Text Files from Disk using ifstreams

 

1.    An ifstream is an object used to transfer data from a file to memory.  The syntax of declaring and initializing (opening) an ifstream object is identical to that of ofstream objects.  Once initialized, we can use the stream-extraction operator (>>) or member functions such as ifstream.get() to retrieve data from a text file.

2.    Reading a text file assumes that the file already exists at some external location.  Before we study the syntax of reading text files, we need to discuss the common situation where a program is unable to open a text file for reading.  See Handout H.A.14.1, Opening Text Files, for more details.  To keep the following programs short, the file opening error code will be left out of section D in the student notes.

3.    This first example program will read a text file of integer data and echo its contents to the monitor.  The contents of "data.txt" are shown to the right of program 14-2.

Program 14-2 

   #include <iostream.h>
#include <fstream.h>
#include <iomanip.h>

main ()
{
  ifstream  infile;
  int   number;

      infile.open ("data.txt",ios::in);

      while (infile >> number)
        cout << setw(4) <<number;

       return 0;

}

data.txt

-2

-1

0

1

2

"eof"

 

    Run output:

    -2  -1   0   1   2 

4.    The sentinel value which terminates the while loop is the eof marker, but it is used in a different manner.  The stream-extraction operator (>>) normally skips whitespace characters (spaces, tabs, newlines) to initialize the target variable, in this case number.  If the stream-extraction operator encounters the end-of-file marker two things occur:

a.     The operator (>>) returns zero (false) upon encountering eof.

b.  The target variable is unchanged.  It retains its previous value or remains undefined if it was previously undefined.

 

5.    The conditional loop read the 5 integers, echoed them to the screen, and terminated when the eof marker was encountered. 

6.    Reading character data from a text file using a program similar to Program 14-2 produces some undesirable results.  The next example, Program 14-3, will attempt to read a two-line text file from disk and echo it to the screen.

 

Program 14-3

    #include <iostream.h>
#include <fstream.h>

main ()

{

       ifstream  infile;
   char    letter;

       infile.open ("cities.txt",ios::in);

       while (infile >> letter)

             cout << letter;

       return 0;

}

cities.txt

 

San Jose

San Francisco

    Run output:

    SanJoseSanFrancisco

       Because the stream-extraction operator skips whitespace when filling target variables, the spaces and linefeed characters are not read and echoed.  If we want to read spaces and linefeed characters we need to use the member function get (char&).

7.    The syntax of the get member function is:

       ifstream&  ifstream.get (char&);

       The function extracts a single character from ifstream into the given character reference.  If the eof marker is encountered the function returns 0 (zero) which can be used to terminate a loop.  Here is an improved version which correctly echoes the spaces and linefeed characters.

Program 14-4

    #include <iostream.h>
#include <fstream.h>
 

    main ()
{

       ifstream  infile;
    char    letter;

        infile.open ("cities.txt",ios::in);

       while (infile.get(letter))
      
cout << letter;

       return 0;

}

cities.txt

 

San Jose

San Francisco

 

    Run output:

    San Jose

    San Francisco 

E.    Streams and Filters

1.    A filter is a program which solves a text file processing problem.  A filter might change lowercase letters to uppercase, count the number of words in a file, or process the blank spaces in a file.

2.    A filter will need to use an ifstream (input) and an ofstream (output).  This last example program illustrates the use of both types of file streams and how to pass streams to a function.

Program 14-5

 //  process filter, capitalize all lowercase letters

 #include <fstream.h>

 void capFile (ifstream &infile, ofstream &outfile);

main ()

{

         ifstream infile ("b:\\files\\cities.txt",ios::in);
         ofstream outfile ("b:\\files\\after.txt",ios::out);

         capFile (infile, outfile);

         return 0;

}

void capFile (ifstream &infile, ofstream &outfile)

{

         char  letter;
         while (infile.get(letter))

         {

                 if ('a' <= letter && letter <= 'z')

                         letter -= 32;

                 outfile << letter;

         }

}

       Here are the two text files, before and after:

                    cities.txt                 after.txt

 

San Jose

San Francisco

 

SAN JOSE

SAN FRANCISCO

 

 

3.    Much of the lab work will involve developing process filters.

 


HandOut 14-1
14-2 Program Pointers

SUMMARY/REVIEW:          Text files can be used to store, manipulate, and move information from one location to another.  Such files can be used to transfer information from one environment (Macintosh to Windows) and even from one application to another (word processor to spreadsheet).  While there are many ways to get the job done, this lesson has attempted to show the cleanest methods to manipulate text files. 

ASSIGNMENT:                     
Lab Exercise L.A.14.1, Squeeze

Lab Exercise L.A.14.2, Average

Text file is numbers.txt -- click here