Home arrow C++ arrow Page 3 - Persistent Data: File Input and Output
C++

Persistent Data: File Input and Output


Persistence is important, particularly to programmers. Data should be persistent as well; that is, it should survive when the program is finished. This article will show you how to make your data persistent by saving it to a file. It is excerpted from chapter 13 of the book C++ Demystified, written by Jeff Kent (McGraw-Hill, 2004; ISBN: 0072253703).

Author Info:
By: McGraw-Hill/Osborne
Rating: 4 stars4 stars4 stars4 stars4 stars / 18
August 25, 2005
TABLE OF CONTENTS:
  1. · Persistent Data: File Input and Output
  2. · First Argument—Specifying the File to Be Opened
  3. · Opening a File for Reading
  4. · Closing a File
  5. · Reading from a File
  6. · Looping Through the File
  7. · Summary

print this article
SEARCH DEVARTICLES

Persistent Data: File Input and Output - Opening a File for Reading
(Page 3 of 7 )

The discussion in the previous section concerning opening a file for writing also applies to opening a file for reading. The primary difference is that the object that calls the open member function, or whose constructor you may use, may be, in addition to an fstream object, an ifstream object instead of an ofstream object. Additionally, the file to be opened for reading must already exist. Unlike opening a file for writing, attempting to open a file for reading will not automatically create it if it does not yet exist. This issue is discussed further in the next section.

The discussion in the previous section concerning opening a file for writing also applies to opening a file for reading. The primary difference is that the object that calls the member function, or whose constructor you may use, may be, in addition to an object, an object instead of an object. Additionally, the file to be opened for reading must already exist. Unlike opening a file for writing, attempting to open a file for reading will not automatically create it if it does not yet exist. This issue is discussed further in the next section.

The following statements use the open member function of the ifstream object to open a file for reading:

ifstream infile;
infile.open("students.dat");

You could accomplish the same purpose using the fstream object, specifying by a file mode flag that the file is being opened for reading only:

fstream afile;
afile.open("students.dat", ios::in);

The following statement uses the ifstream constructor to open a file for reading:

ifstream infile ("students.dat");

You could accomplish the same purpose using the fstream constructor, specifying in the second argument the file mode flag that the file is being opened for reading only:

fstream afile ("students.dat", ios::in);

Opening a File for Reading and Writing

You can use the fstream object to open a file for reading and for writing. You cannot use either the ofstream or ifstream object for this purpose, as an ofstream object cannot be used to read files, and an ifstream object cannot be used to write to files.

You can use the object to open a file for reading and for writing. You cannot use either the or object for this purpose, as an object cannot be used to read files, and an object cannot be used to write to files.

The following code fragment uses the open member function of the fstream object for this purpose:

fstream afile;
afile.open("students.dat", ios::in | ios::out);

Alternatively, you can use the two-argument fstream constructor:

fstream afile ("students.dat", ios::in | ios::out);

Both alternatives use the bitwise or operator (|) discussed in the earlier section “Second Argument—File Mode” to combine the file mode flags for input and output.


NOTE: Combining the ios::in and ios::out flags changes expected defaults. The ios::out flag by itself causes an existing file to be overwritten, and the ios::in flag by itself requires that the file already exist. However, when the ios::in and ios::out files are used together, the file’s existing contents are preserved, and the file will be created if it does not already exist.

NOTE: Combining the ios::in and ios::out flags changes expected defaults. The ios::out flag by itself causes an existing file to be overwritten, and the ios::in flag by itself requires that the file already exist. However, when the ios::in and ios::out files are used together, the file’s existing contents are preserved, and the file will be created if it does not already exist.

Checking if the File Was Opened

You should not assume that a file was successfully opened with the open member function or the constructor. There are several reasons why the file may not have been successfully opened. If the file was not successfully opened, but your code casually assumes it was and attempts to read from, or write to, the file, errors may occur.

You should not assume that a file was successfully opened with the member function or the constructor. There are several reasons why the file may not have been successfully opened. If the file was not successfully opened, but your code casually assumes it was and attempts to read from, or write to, the file, errors may occur.

The primary difference between opening a file for reading and for writing is that while you can write to a file that does not exist—the operating system simply creates the file—you cannot read from a file unless it already exists. Therefore, you should check if the file was opened successfully for reading before you attempt to read it.

If the file could not be opened for reading, then the value of the ifstream object that called the open function is NULL. As you may recall from Chapter 11, NULL is a constant defined in several standard library files whose value is zero.

Alternatively, if the file could not be opened for reading, then the ifstream object’s fail member function returns true, which is the fail function’s return value if a file operation, in this case attempting to open a file, was not successful.

The following code illustrates the use of both checking if the ifstream object used to call the open function is NULL and whether the ifstream object’s fail member function returns true:

#include <fstream>
#include <iostream>
using namespace std;
int main ()
{
ifstream infile;
infile.open("students.dat");
cout << "(infile) = " << infile << endl;
cout << "(infile.fail()) = " << infile.fail() << endl;
return 0;
}

If the students.dat file does not yet exist, the output would be

(infile) = 00000000
(infile.fail()) = 1

However, if there was a file named students.dat in the same directory as your program, then the output would be

(infile) = 0012FE40
(infile.fail()) = 0

The value, 0012FE40, is the address of the ifstream variable infile, and of course could be different if you run this program.

Unlike an ifstream object, an ofstream object that attempts to open a file that does not yet exist is not NULL, and its fail member function would return false, because the operating system will create the file if it does not already exist. However, opening a file for writing is not always successful. For example, before you run the following program, create a file named students.dat in the same directory as your program but, through its properties, check read only:

#include <fstream>
#include <iostream>
using namespace std;
int main ()
{
ofstream outfile;
outfile.open("students.dat");
cout << "( outfile) = " << outfile << endl;
cout << "( outfile.fail()) = " << outfile.fail() << endl;
return 0;
}

The following output reflects that the ofstream object is NULL, and its fail function returns true, because you cannot open for writing a file that is read only.

(outfile) = 00000000
(outfile.fail()) = 1

If you cannot open a file for reading or writing, then you do not want to proceed to execute the code that reads from, or writes to, the file. Instead, you may want to stop execution of the function, as in the following code fragment:

ifstream infile;
infile.open("students.dat");
if (infile == NULL)
{
cout << "Error in opening file for reading";
return 0;
}
// code to read from file


NOTE: For purposes of brevity and avoiding repetitive code, some of the following code in this chapter omits checking if a file was opened successfully.

blog comments powered by Disqus
C++ ARTICLES

- Intel Threading Building Blocks
- Threading Building Blocks with C++
- Video Memory Programming in Text Mode
- More Tricks to Gain Speed in Programming Con...
- Easy and Efficient Programming for Contests
- Preparing For Programming Contests
- Programming Contests: Why Bother?
- Polymorphism in C++
- Overview of Virtual Functions
- Inheritance in C++
- Extending the Basic Streams in C++
- Using Stringstreams in C++
- Custom Stream Manipulation in C++
- General Stream Manipulation in C++
- Serialize Your Class into Streams in C++

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 

Developer Shed Affiliates

 




© 2003-2017 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials