A few short notes and examples on file I/O

The basic sequence of events is as follows:

The library we'll be using is fstream, the data type used for input files is ifstream, and the data type for output files is ofstream.

The first example below illustrates some file input (reading from a file), while the second example illustrates file output (writing to a file). (The formats should look pretty similar to the use of cin and cout.)

// file input example
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

// put a maximum length on the file names you'll handle
const int MaxNameLength = 256;

int main()
{
   // declare an ifstream variable to use for reading from a file
   ifstream myfile;

   // get the user to type in a filename,
   char fname[MaxNameLength];
   cout << "Please enter a filename:" << endl;
   cin.getline(fname, MaxNameLength);

   // try to open the file 
   myfile.open(fname);

   // if the file did not open successfully print an error message
   if (myfile.fail()) {
      cout << "Sorry, could not open file " << fname << endl;
   }

   else {
      // read various data values from the file
      // (like cin, except the info comes from the file)
      float f; int i; string s; char c;
      myfile >> f >> i >> s >> c;

      // read a line of text into a string using the getline function
      getline(myfile, s);

      // read a line of text into a character array using the getline method
      char text[80];
      myfile.getline(text, 80);

      // now try reading one character at a time from the file
      //     and displaying it on the screen,
      // stopping when you reach the end of the file
      // (eof() returns true when you've attempted
      //  one read 'past' the last char in the file)
      while (!myfile.eof()) {
         cout << c;
         myfile.get(c);
      }

      // close the file
      myfile.close();
   }
}

// file output example
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

// put a maximum length on the file names you'll handle
const int MaxNameLength = 256;

int main()
{
   // declare an ofstream variable to use for reading from a file
   ofstream myfile;

   // get the user to type in a filename,
   char fname[MaxNameLength];
   cout << "Please enter a filename:" << endl;
   cin.getline(fname, MaxNameLength);

   // try to open the file 
   myfile.open(fname);

   // if the file did not open successfully print an error message
   if (myfile.fail()) {
      cout << "Sorry, could not open file " << fname << endl;
   }

   else {
      // print data to the file, just like using cout
      myfile << "blah blah blah";\n
      for (int i = 0; i < 10; i++) {
          myfile << "line number " << i << endl;
      }

      // close the file
      myfile.close();
   }
}

Error checking and end of file

There is an alternate approach to handling both error checking and end-of-file testing with file input.

If we have an ifstream variable, such as myfile above, then a statement such as myfile >> somevar; returns a value (in addition to actually reading data into somevar).

That value will be 0 if the >> operation failed, whether it is because of an invalid data value in the file (e.g. text when you're expecting an int) or because of hitting the end of the file.

As a result, we can use if (myfile >> somevar) { to test whether or not an attempted read was successful.

This is illustrated in the example below (the table shows the program on the left, the contents of the two files in the middle, and the resulting output on the right).

program contents of files
test1 and test2
resulting output
#include <iostream>
#include <fstream>
using namespace std;

int main()
{
   ifstream fpin1, fpin2;
   int i;

   fpin1.open("test1");
   if (!fpin1.fail()) {
      // read from file test1 until you hit
      // invalid data or end of file
      while (fpin1 >> i) {
         cout << i << endl;
      }
      fpin1.close();
   }

   fpin2.open("test2");
   if (!fpin2.fail()) {
      // read from file test2 until you hit
      // invalid data or end of file
      while (fpin2 >> i) {
         cout << i << endl;
      }
      fpin2.close();
   }
}
1
2
3

10 20 xyz
1
2
3
10
20


Note: after the failed reads, the fail method will return true even if there is more data in the file.