Disk File I/O with Streams in C++

By
Last updated:

Most programs need to save data to disk file I/O and read it back in. Working with disk file I/O requires another set of classes: ifstream for input, fstream for both input and output, and of stream for output. Objects of these classes can be associated with disk files, and we can use their member functions to read and write to the files.

Referring back to Figure, you can see that ifstream is derived from istream, fstream is derived from iostream, and ofstream is derived from ostream. These ancestor classes are in turn derived from ios. Thus the file oriented classes derive many of their member functions from more general classes. The file-oriented classes are also derived, by multiple inheritance, from the fstreambase class. This class contains an object of class filebuf, which is a file oriented buffer, and its associated member functions, derived from the more general streambuf class. You don’t usually need to worry about these buffer classes.

The ifstream, ofstream, and fstream classes are declared in the FSTREAM file.

C programmers will note that the approach to disk I/O used in C++ is quite different from that in C. The old C functions, such as fread() and fwrite(), will still work in C++, but they are not so well suited to the object oriented environment. The new C++ approach is considerably cleaner and easier to implement. (Incidentally, be careful about mixing the old C functions with C++ streams. They don’t always work together gracefully, although there are ways to make them cooperate.)

Formatted File I/O

In formatted I/O, numbers are stored on disk as a series of characters. Thus 6.02, rather than being stored as a 4-byte type float or an 8-byte type double, is stored as the characters ‘6’, ‘.’, ‘0’, and ‘2’. This can be inefficient for numbers with many digits, but it’s appropriate in many situations and easy to implement. Characters and strings are stored more or less normally.

Writing Data

The following program writes a character, an integer, a type double, and two string objects to a disk file I/O. There is no output to the screen. Here’s the listing for FORMATO:

// formato.cpp
// writes formatted output to a file, using <<
#include <fstream>     //for file I/O
#include <iostream>
#include <string>
using namespace std;
int main()
{
char ch = ‘x’;
int j = 77;
double d = 6.02;
string str1 = “Kafka”; //strings without
string str2 = “Proust”; // embedded spaces
ofstream outfile(“fdata.txt”); //create ofstream object
outfile << ch //insert (write) data
<< j
<< ‘ ‘ //needs space between numbers
<< d
<< str1
<< ‘ ‘ //needs spaces between strings
<< str2;
cout << “File written\n”;
return 0;
}

Here we define an object called outfile to be a member of the ofstream class. At the same time, we initialize it to the file FDATA.TXT. This initialization sets aside various resources for the file, and accesses or opens the file of that name on the disk. If the file doesn’t exist, it is created. If it does exist, it is truncated and the new data replaces the old. The outfile object acts much as cout did in previous programs, so we can use the insertion operator (<<) to output variables of any basic type to the file. This works because the insertion operator is appropriately overloaded in ostream, from which ofstream is derived.

When the program terminates, the outfile object goes out of scope. This calls its destructor, which closes the file, so we don’t need to close the file explicitly.

There are several potential formatting glitches. First, you must separate numbers (such as 77 and 6.02) with nonnumeric characters. Since numbers are stored as a sequence of characters, rather than as a fixed length field, this is the only way the extraction operator will know, when the data is read back from the file, where one number stops and the next one begins. Second, strings must be separated with whitespace for the same reason. This implies that strings cannot contain imbedded blanks. In this example we use the space character (‘ ‘) for both kinds of delimiters. Characters need no delimiters, since they have a fixed length.

You can verify that FORMATO has indeed written the data by examining the FDATA.TXT file with the Windows WORDPAD accessory or the DOS command TYPE.

Reading Data

We can read the file generated by FORMATO by using an ifstream object, initialized to the name of the file. The file is automatically opened when the object is created. We can then read from it using the extraction (>>) operator.

Here’s the listing for the FORMATI program, which reads the data back in from the FDATA.TXT file:

// formati.cpp
// reads formatted output from a file, using >>
#include <fstream>      //for file I/O
#include <iostream>
#include <string>
using namespace std;
int main()
{
char ch;
int j;
double d;
string str1;
string str2;
ifstream infile(“fdata.txt”); //create ifstream object
//extract (read) data from it
infile >> ch >> j >> d >> str1 >> str2;
cout << ch << endl //display the data
<< j << endl
<< d << endl
<< str1 << endl
<< str2 << endl;
return 0;
}

Here the ifstream object, which we name infile, acts much the way cin did in previous programs. Provided that we have formatted the data correctly when inserting it into the file, there’s no trouble extracting it, storing it in the appropriate variables, and displaying its contents. The program’s output looks like this:

x
77
6.02
Kafka
Proust

Of course the numbers are converted back to their binary representations for storage in the program. That is, the 77 is stored in the variable j as a type int, not as two characters, and the 6.02 is stored as a double.

Read More Topics
Object oriented programming
C++ Object as physical objects
The relationship between C and C++
Characteristics of object oriented programming

Santhakumar Raja

Hello The goal of this blog is to keep students informed about developments in the field of education. encourages pupils to improve as writers and readers.

For Feedback - techactive6@gmail.com

Leave a Comment