CS 1440 Lab 6

Cover sheetPrevious ActivityNext Activity


Activity 6-5: I/O with Files

Activity Goals

Activity Procedure

Okay, this is a long activity so hang in there!

Your C++ program can read from Unix files and write to Unix files.  There are five steps that you must remember when working with files in your C++ programs and sample C++ statements for each step. 

1.      You must include the proper header file.

       If you're reading in the file name:

#include  <fstream>

#include  <string>

2.      You must declare a variable of the correct file data type (input or output)

       If you're reading the file name into f_name:

ifstream  fin;
ofstream  fout;

string  f_name;

3.      You must "connect" your program variable (the file's internal name) with a Unix file (the file's external name).  Note this is the ONLY time you refer to the Unix file name.

       If you're reading the file name into f_name:

fin.open("infile.txt");
fout.open("outfile.txt");

 
fin.open(f_name.c_str());
fout.open(f_name.c_str());

4.      You then use the variable (the internal name) to read/write the file.

 

fin  >>  . . . ;
fout  <<  . . .;

5.      You must "disconnect" your program variable from the Unix file.

 

fin.close();
fout.close();

 

Let's write to a file.  Copy and paste the following program into a file named hout.C and compile and run it.  What happened?  It doesn't look like it worked.  Look at the program carefully and see that the output went to a file.  So, give Unix the "ls" command and see that it created the file hello.txt!  Verify the contents of this file are what your C++ program wrote into the file.

#include  <iostream>
#include  <fstream>

using namespace std;
int main() {
     ofstream  outfile;
     outfile.open("hello.txt");
     outfile << "Hello I am hello.txt" << endl;
     outfile << 7 << " " << 11 << endl;
     outfile.close();
}

Now, let's read from a file.  Copy and paste the following program into a file named hin.C and compile and run it.  Where did all this text come from?  Of course you know it came from the file hello.txt!!

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

using namespace std;
int main() {
     ifstream  ifile;
     string  word;
     ifile.open("hello.txt");
     while  (ifile >> word)
          cout << word << endl;
     ifile.close();
}

Yes, you may read and write within one C++ program.  In fact you can read from several and write to several in a single C++ program.

Two final topics related to file I/O.  (1) It might be possible that you try to open a file that does not exist.  You can check to see if the open failed by using the fail call as shown below in a snippet of code.

     file_variable.open("afile.txt");
     if (file_variable.fail()) {
          cout  <<  "Open failed" << endl;
          return ;
     }

And (2) when reading from an input file, you usually need to know when you have reached the end of the file.  One way that often works is to do the read in the loop condition as shown in the example above and in your hin.C file.  The other way is to use the stream's eof() command.  This returns true after the end of the file has been detected.  The tricky thing with eof() is that you have to attempt to read past the end of the file to actually notice that you are at the end.  Modify the loop in hin.C to look like the one below.

     // while not end of file, read & output
     while  ( !  ifile.eof( ) ) {
          ifile >> word;
          cout << word << endl;
     }

Compile and run this new version of hin.C do you see how the 11 printed twice!  But there is only one 11 in the input file hello.txt.  What happened?  The "word" 11 was successfully read and output.  The end of file has not yet been detected so we loop again.  Then the read into word failed, BUT THE VALUE OF THE VARIABLE WAS UNALTERED.  So of course 11 was displayed again.  NOW, the program knew it was at the end of the file and the loop stopped.  The following would work more correctly (you do not need to copy and paste this though).  Notice how we check to see if the read caused end-of-file to be detected.

           while  ( !  ifile.eof( ) ) {
                ifile >> word;
                if ( ! ifile.eof()) {
                    cout << word << endl;
                }
           }
which requires testing for end of file twice in each pass of the loop. By reading the first word before we first enter the body of the loop and rearranging the statements in the loop, we can do it with only one test per pass:
           ifile >> word;
           while  ( !  ifile.eof( ) ) {
                cout << word << endl;
                ifile >> word;
           }

Activity Followup

In a file named copy.C write a C++ program that copies the contents of one file into another file.  Your program should prompt for the input Unix file name and the output Unix file name.  Then read the data in the input file and output it to the output file.  One last thing.  The open( ) command for streams does not like strings as arguments.  So, you'll need to use a special type of type-conversion function (like you did in Lab4).  This one looks like the following:

 

ifstream  ifile;
string s;
   . . .
ifile.open(s.c_str());