Reading from a File


You input or read information from a file into your program using the stream extraction operator (>>) just as you use that operator to input information from the keyboard. The only difference is that you use an ifstream (or fstream ) object instead of the cin object.

The following program builds on the previous one. After writing information inputted by the user to a file named students.dat, the program reads information from the file and outputs it onto the screen:

 #include <fstream> #include <iostream> using namespace std; int main () {  char data[80];  ofstream outfile;  outfile.open("students.dat");  cout << "Writing to the file" << endl;  cout << "===================" << endl;   cout << "Enter class name: ";   cin.getline(data, 80);  outfile << data << endl;  cout << "Enter number of students: ";   cin >> data;  cin.ignore();  outfile << data << endl;  outfile.close();  ifstream infile;   cout << "Reading from the file" << endl;   cout << "=====================" << endl;   infile.open("students.dat");   infile >> data;   cout << data << endl;   infile >> data;   cout << data << endl;   infile.close();  return 0; } 

Sample input and output:

 Writing to the file =================== Enter class name: Programming Enter number of students: 32 Reading from the file ===================== Programming 32 

Reading a Line of a File

With the same program, try entering a class name with an embedded space. The following is some sample input and output:

 Writing to the file =================== Enter class name: Programming Demystified Enter number of students: 32 Reading from the file ===================== Programming Demystified 

The following are the contents of the file after the inputted data was written to it:

 Programming Demystified 32 

The first read of the file did not read the first line of the file, Programming Demystified. Instead, the first read of the file only read the word Programming and then stopped . Consequently the second line of the program read the remainder of the first line of the file, Demystified, instead of the number of students.

The ifstream object together with the stream extraction operator reads the file sequentially, starting with the first byte of the file. The first attempt to read the file starts at the beginning of the file and goes to the first whitespace character (a space, tab, or new line) or the end of the file, whichever comes first. The second attempt starts at the first printable character after that whitespace, and continues to the next whitespace character or the end of the file, whichever comes first.

The first read attempt only read Programming, not Programming Demystified, because the read stopped at the whitespace between Programming and Demystified. The second attempt read Demystified. There were no further read attempts, so the number of students, 32, was never read.

This should seem like d j   vu. We encountered a similar issue in Chapter 10 using the cin object with the stream extraction operator (>>). As in Chapter 10 with the cin object, the solution is to use getline.

If you are working with C-strings, then you should use the getline member function. The only difference between using the getline member function here and in Chapter 10 is that here the getline member function is called by an ifstream or fstream object instead of a cin object. Accordingly, we need to replace the two calls to infile >> data with the following:

 infile.getline(data, 80); 

You also can use getline with the C++ string class. The only difference between using the getline member function here and in Chapter 10 is that here the first argument of the getline member function is an ifstream or fstream object instead of a cin object. Accordingly, we need to replace the two calls to infile >> data with the following:

 getline(infile, data); 

The following modification of the previous program uses the getline function with the C++ string class:

 #include <fstream> #include <iostream> #include <string> using namespace std; int main () {  string data;  ofstream outfile;  outfile.open("students.dat");  cout << "Writing to the file" << endl;  cout << "===================" << endl;   cout << "Enter class name: ";   getline(cin, data);   outfile << data<< endl;  cout << "Enter number of students: ";   cin >> data;  cin.ignore();  outfile << data<< endl;  outfile.close();  ifstream infile;   cout << "Reading from the file" << endl;   cout << "=====================" << endl;   infile.open("students.dat");   getline(infile, data);  cout << data << endl;   getline(infile, data);  cout << data << endl;   infile.close();  return 0; } 

As the following sample input and output reflects, the first read now reads the entire first line of the file even when that line contains embedded spaces:

 Writing to the file =================== Enter class name: Programming Demystified Enter number of students: 32 Reading from the file ===================== Programming Demystified 32 

Looping Through the File

In the previous program, exactly two read attempts were made because we knew there were two lines of data in the file, no more, no less. However, often we may not know the number of pieces of data to be read. All we want is to read the file until we have reached the end of it.

The ifstream object has an eof function, eof being an abbreviation for end of file. This function, which takes no arguments, returns true if the end of the file has been reached, and false if otherwise .

However, the eof function is not as reliable with text files as it is with binary files in detecting the end of the file. The eof function s return value may not accurately reflect if the end of the file was reached if the last item in the file is followed by one or more whitespace characters. This is not an issue with binary files since they do not contain whitespace characters .

A better choice is the fail member function, discussed in the earlier section Checking if the File Was Opened. The following code fragment shows how to use the fail member function in reading a file until the end of the file is reached:

 ifstream infile;  infile.open("students.dat");  infile >> data;  while(!infile.fail())  {  infile >> data;  cout << data;  }  infile.close(); 

The preceding code fragment has two infile >> data statements, one before the loop begins, the other inside the loop. The reason is that the end of file is not detected until after a read attempt is made. Thus, if the infile >> data statement before the loop was omitted and the file was empty, the cout << data statement would execute before an attempt was made to detect if the end of file had been reached.

Note  

A do while loop could be used instead of a while loop. This would dispense with the need to check for end of file before entering the loop, but add the requirement to check inside the loop if (using an if statement) end of file had been reached. This is the usual tradeoff between while and do while loops .

Modifying the previous program, the code now would read

 #include <fstream> #include <iostream> #include <string> using namespace std; int main () {  string data;  ofstream outfile;  outfile.open("students.dat");  cout << "Writing to the file" << endl;  cout << "===================" << endl;   cout << "Enter class name: ";   getline(cin, data);   outfile << data<< endl;  cout << "Enter number of students: ";   cin >> data;  cin.ignore();  outfile << data<< endl;  outfile.close();  ifstream infile;   cout << "Reading from the file" << endl;   cout << "=====================" << endl;   infile.open("students.dat");   getline(infile, data);  while(!infile.fail())  {  cout << data << endl;   getline(infile, data);  }  infile.close();  return 0; } 



C++ Demystified(c) A Self-Teaching Guide
C++ Demystified(c) A Self-Teaching Guide
ISBN: 72253703
EAN: N/A
Year: 2006
Pages: 148

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net