Basics of Accessing Files in C++

C++ Taking the Bull by the Horns - Part 25

Chrys Forcha
Introduction
This is part 25 of my series, C++ Taking the Bull by the Horns. In this part of the series, we see how to access files in C++. I assume that you have read the previous parts of the series before reading this one, because the knowledge here is based on knowledge gained from the previous parts of the series. We shall consider only text files and those, which are in the working directory (so we shall not need to bother about directory path). This means that you test code should remain in the working directory.

Note: If you cannot see the code or if you think anything is missing (broken link, image absent), just contact me at forchatrans@yahoo.com. That is, contact me for the slightest problem you have about what you are reading.

File Classes and Streams
In order for you to use a file in the hard disk or some other drive, you have to do what is called opening the file. With this the content of the file is copied into memory. This area in memory that has the content of the file is called a stream. Whatever you want to do to the file (modifying the file, adding text to the end of the file, or just reading the file) you do it to the stream. After that you have to do what is called closing the file. When a file is closed, the content of the stream is copied to the file in the disk. Any modification of stream content or adding of text to the end of the stream is reflected in the file in the disk after closing.

A file may not exist in the disk. This means you have to create it. For this purpose, you still have to use the opening process (see below). A stream for the newly (not existing) opened file is created. You send information to the stream. When you close the file, effectively closing the stream, the content of the stream is copied to the disk for the first time. Closing a file means putting an end to the association between the stream and the corresponding file in the disk, after the content of the stream has just been copied to the file, which might or might not have existed, in the disk.

Note: the content of the stream is the file content copied from disk, if the file existed in the disk before it was opened.

There are three classes, which are used to access files. These classes are predefined; you do not have to define them (type them out). The names of these classes are ofstream, ifstream and fstream. When an object is created from any of these classes, a stream in memory is associated with the object.

To use these classes you need to include a header file called the fstream header in your program. Once these headers have been included in you program file, you just instantiate objects of type, ofstream, ifstream or fstream as if you had typed out the classes yourself. Of course, these classes have methods that you use to access the streams of the corresponding created (instantiated) objects.

open and close Methods
Each of the above three classes has an open and a close method. The syntax for the open method is,

streamObj.open(filename, mode);

streamObj is the object created form one of the classes. This is followed by a dot and then you have the opened method call. The first argument in the parentheses is the file name in double quotes. I will explain the role of the mode (second) argument as we go along. The mode argument is optional; that is you do not have to use it. The syntax for the close method is,

streamObj.close();

streamObj is the object that was used in the open method. Next you have the dot as expected, then you have the close method call. This call takes no arguments.

The is_open Method
When you call the open method for any of the classes, the file may not be opened if there is an error. For example, the drive may have bad sectors and the file would not be opened. You need to use the is_open method to check if the file was successfully opened. This method returns a Boolean true if the file was successfully opened, or a Boolean false, if it was not. If a file was successfully opened, then you can proceed to access the stream, after which you close the file. When you close the file, everything in the stream is saved into the disk. If the opening process was not successful, then you should not proceed to use the file. The is_open method syntax is

streamObj.is_open();

Its object is the same object you used in the open method. It takes no argument. Of course, there is a dot between the object identifier and the method name.

The ofstream Class
The ofstream class is used basically to produce a new file. For simple cases, you do not need the mode argument to use this class. The syntax to create an object from the class, ofstream is

ofstream fileStrm;

You begin with the class name followed by a space then the identifier (name) of the object (any name you like). I have given the name, fileStrm, above. To send a line of text to the stream you do this:

fileStrm
You begin with the identifier of the object. Next you have the
#include
#include
using namespace std;

int main()
{
ofstream writeStrm;
writeStrm.open("myfile.txt");
if (writeStrm.is_open())
{
writeStrm writeStrm writeStrm }
writeStrm.close();

return 0;
}

Note the inclusion of the fstream header file. The three writing lines can be reduced to one as follows:

writeStrm
In the long string above, the \n character forces the next potion of the string to the next line.

A Bit about the string Class
There is a predefined class called the string class. This class is used to instantiate (create) and object that will hold a string. The syntax to create such an object is,

string myStr;

where myStr is the identifier you give for the string object; you can give any name you want. The header file that provides this class is called string.

Hey, you can also use the string class as object type for your array elements. The declaration of the array is something like,

string myArray[10];

The object type for each of the array element is string. The array identifier above is myArray. The declaration above assumes that there will be 10 elements in the array. Each element in the array will be a string (phrase).

The getline Function
The string header file also has a function called the getline function whose syntax, in simple terms is:

getline(streamObj, strObjIdent)

The first argument is the identifier of a stream object. The second is the identifier of a string object, instantiated from the string class. Now this getline function will read a line of text from a stream and put it in the object identified by strObjIdent. You can then display (print) the content of strObjIdent. The getline function gets the text of the line without the ending \n character.

The ifstream Class
This is basically used to read a file. For simple cases, you do not need the mode argument to use this class. The syntax to create an object from the class, ifstream is

ifstream fileStrm;

You begin with the class name followed by a space then the identifier (name) of the object (any name). To read a line from the stream, you do this:

getline(streamObj, strObjIdent)

I have explained this function and its argument above. The following code reads the three lines of the file created above. Read and try it.

#include
#include
#include
using namespace std;

int main()
{
ifstream readStrm;
string line;
readStrm.open("myfile.txt");
if (readStrm.is_open())
{
getline(readStrm, line);
cout cout cout readStrm.close();

return 0;
}

The \n character forces the next printed (display) line to the next line. Note the inclusion of the string header.

File Position Indicator
When a file is opened successfully, a stream for the file is established. There is what is called a file position indicator. When a file is just opened, everything being equal, this indicator points to the beginning of the file stream. Whatever you do to the stream will happen at the character or line the file position indicator is pointing to. When you read a line of text, the file position indicator would point to the next line to be read, everything being equal. When you write a line, the file position indicator would point to the end of the line just written, everything being equal.

The eof method
The eof method for end-of-file is used to detect whether the file position indicator has reached the end of the stream, which corresponds to the end of file in the disk. The return value of this method is true (of type _Bool) when the end of file is reached, or false when the end of file has not been reached.

The syntax to use the eof method is,

streamObjIdent.eof()

You start with the stream object identifier, then the dot and then the method call. It takes no argument.

In the following code, lines of the text file we saved are copied into an array. The code uses the eof method, to know when to stop reading the file. The contents of the array are then displayed.

#include
#include
#include
using namespace std;

int main()
{
ifstream rdStrm;
string lineArr[100];
int i = 0;
rdStrm.open("myfile.txt");
if (rdStrm.is_open())
{
while (!rdStrm.eof())
{
getline(rdStrm, lineArr[i]);
++i;
}
}
rdStrm.close();

for (i=0; i {
cout }

return 0;
}
The first line in the code includes the header, fstream. You need this to have any of the three types of file objects from the three types of file (stream) classes. The second line includes the string header. This is for the declaration of the string array. Each line from the file will be read into the array. The next line in the code includes iostream. This is for the cout object.

The first line in the main function, creates a file stream object for read-only. The next line creates the array of strings of the string class. It assumes that there are not more than 100 lines in the text file. There is next the declaration of a counter for the different lines in the file and for a for-loop to count through the array. The next line checks if the file was successfully opened. If it was, then the if-block is executed and then the file is closed.

In the if-block, there is a while loop. Inside the while loop, one line from the stream is read. After the reading of each line, the file position indicator points to the next line in the stream. So as the while-loop repeats, all the lines in the stream are accessed. The getline statement in the while-loop reads each line. The second statement in the while-loop increments the counter so that the next line read should be sent to the next cell of the array. The while-loop is repeated until the end-of-file is reached. Note how eof is coded (checked) in the condition of the while-loop. End-of-file means end of stream.

After the if-block, you have the for-loop. This for-loop displays the content (lines) of the array.

Try the above code and note that all the lines of the file (array) will be displayed but in one line on the monitor. This is because the getline function does not read the \n character at the end of each line in the file.

The fstream Class
The fstream class is used when you want to edit (modify) a file. With this class you can write to a file and read from it. If you are writing to a file, if it did not exist it will be created. The syntax to create an object from the class, fstream is

fstream fileStrm;

You begin with the class name followed by a space then the identifier (name) of the object (name of your choice). Note that the name of a header is fstream. In that header, one of the classes is fstream, having the same name as the header.

The fstream class (object) uses the mode argument in its open method. Some of the possible values for the mode argument and their meanings are as follows:

ios::in : Open for reading.
ios::out : Open for writing.
ios::app : Open to append; that is add new content at the end of an already existing file content.
ios::trunc : Open for writing, but first erase all the previous content of the file in disk.

You use the above value without quotes. If you want to change (edit) text anywhere in the file, then you should use the following for the argument:

ios::in | ios::out

These are the values for reading and writing, linked by the | character.

Simple Editing of Text Files
A simple way to edit a file is as follows:

Open the file with an ofstream object for read-only. Copy the contents of the file into an array. Close the file (close the stream object). Next modify the contents of the array. Open the file again, but this time, with the fstream object and the, ios::trunc argument. This argument will erase the previous content of the file. Next copy the contents of the array to the fstream stream just created. Close the stream and the array content copied including the file changes would be saved. In that way you would have modified the file. The following code illustrates this. Read and try it.

#include
#include
#include
using namespace std;

int main()
{
ifstream rdStrm;
string lineArr[100];
int i = 0; //counter for line number in text.
rdStrm.open("myfile.txt");
if (rdStrm.is_open())
{
while (!rdStrm.eof())
{
getline(rdStrm, lineArr[i]);
++i;
}
}
rdStrm.close();

//change all the array elements
lineArr[0] = "This is line A.\n";
lineArr[1] = "This is line B.\n";
lineArr[2] = "This is line C.\n";

//Use fstream class to save changes
fstream rdWriteStrm;
rdWriteStrm.open("myfile.txt", ios::trunc);
int j = 0; //counter for array - the value of i should now be 2, i.e. 3-1
rdWriteStrm.open("myfile.txt");
if (rdWriteStrm.is_open())
{
for (j=0; j {
rdWriteStrm }
}
rdWriteStrm.close();

return 0;
}

Use you operating system to open the file, myfile.txt and note that the three lines that were there have been replaced. Since the file ended with a \n character, you may see an extra line in the file. If you do not want this extra line, then do not end your file with the \n character.

Well, we have come to the end of this tutorial. We continue in the next part.

Chrys

To arrive at any of the parts of this series, just type the corresponding title below in the Search Box of this page and click Search (you can also use any available links):

C++ Taking the Bull by the Horns - Part 1
C++ Taking the Bull by the Horns - Part 2
C++ Taking the Bull by the Horns - Part 3
C++ Taking the Bull by the Horns - Part 4
C++ Taking the Bull by the Horns - Part 5
C++ Taking the Bull by the Horns - Part 6
C++ Taking the Bull by the Horns - Part 7
C++ Taking the Bull by the Horns - Part 8
C++ Taking the Bull by the Horns - Part 9
C++ Taking the Bull by the Horns - Part 10
C++ Taking the Bull by the Horns - Part 11
C++ Taking the Bull by the Horns - Part 12
C++ Taking the Bull by the Horns - Part 13
C++ Taking the Bull by the Horns - Part 14
C++ Taking the Bull by the Horns - Part 15
C++ Taking the Bull by the Horns - Part 16
C++ Taking the Bull by the Horns - Part 17
C++ Taking the Bull by the Horns - Part 18
C++ Taking the Bull by the Horns - Part 19
C++ Taking the Bull by the Horns - Part 20
C++ Taking the Bull by the Horns - Part 21
C++ Taking the Bull by the Horns - Part 22
C++ Taking the Bull by the Horns - Part 23
C++ Taking the Bull by the Horns - Part 24
C++ Taking the Bull by the Horns - Part 25

Published by Chrys Forcha

I have more than 10 years experience in computer programming, software, electronics and telecommunications. I have a First Degree in Electronics and a Master's Degree in Technical Education. As well a...  View profile

2 Comments

Post a Comment
  • Chrys Forcha8/31/2010

    Thanks Greg

  • Greg Seltz7/17/2010

    Great articles...these should be perfect for individuals who are searching Google to learn more about C++

Displaying Comments

To comment, please sign in to your Yahoo! account, or sign up for a new account.