C++

How to Use C++ fstream

The fstream term stands for File Stream. Stream refers to a sequence of characters moving from the disk to the C++ program or from the C+ program to the disk. Moving characters from a file in disk to the program is inputting. Moving characters from the program to a file in the disk is outputting. Input-file-stream abbreviated as ifstream is structured by the template class, basic_ifstream. Output-file-stream abbreviated, ofstream is structured by the template class, basic_ofstream.

It is possible for inputting and outputting to take place in one session. This is made possible by the class template, basic_fstream. Now, fstream is a synonym for basic_fstream. fstream, which is still basic_fstream, uses basic_ifstream and ofstream to operate.

In order to do input alone, do output alone, or both in one session, it suffices to start the C++ program with the following includes and namespace invocations:

#include <fstream>
#include <iostream>
using namespace std;

This tutorial has four main sections: opening and closing of a file stream, output file stream, appending, input file stream, and editing a file. Editing a file means inputting and outputting a stream.

Article Content

Opening and Closing a File Stream

Before a stream can be opened, a stream object has to be created. Opening a stream means establishing a channel between the C++ program and the file in disk. This is accomplished through which the sequence of characters will move to the file; or through which sequence of characters will leave the file and come to the program; or through which characters will move to-and-fro.

A stream is opened only for writing (output), reading (input), or both reading and writing. It can also be opened for other reasons.

Before opening a stream, the stream object has to be constructed. The simplest way to express it is as follows in the C++ main() function:

fstream strm;

Now, with the strm object, the fstream member functions, open() and close() can be used, preceding each with the dot operator. The following statement can be used to open an fstream for reading:

void open("path/to/and/the/file", ios_base::in);

The open() member function returns void.

With the stream object, the statement would be:

strm.open("./myfile", ios_base::in);

Since the open() member function returns void, to know if the file in the disk was successfully opened, use the member function:

bool is_open() const;

It returns zero for false if the file did not open and 1 for true if the file opened. Now our program looks like this so far:

#include <fstream>
#include <iostream>
using namespace std;

int main(){
    fstream strm;
    strm.open("./myfile", ios_base::in);

    if (strm.is_open()){
                cout << "Open success" << endl;
    }
    else {
        cout << "Open failed" << endl;
        return 1;
    }

    return 0;
}

To open a file for writing, use this flag:

strm.open("path/to/and/the/file", ios_base::out);

ios_base::in means open for reading and ios_base::out means open for writing. To open a file for reading and writing, use:

strm.open("path/to/and/the/file", ios_base::in | ios_base::out);

Note: the presence of “ios_base::in | ios_base::out”, which uses logical OR to combine both flags as a single argument to the function.

Closing a stream means closing the channel through which data can be sent to and fro between the program and the file. No more datum can be sent in either direction using that channel. Closing the stream is not closing the stream object. The same stream can still be used to open a new channel, which should be closed after use in transmission of data. Make it a habit of closing any file stream, after it has been opened. When a stream is closed, any data in memory that was supposed to have been in the file is sent to the file before actually closing. The member function prototype to close fstream is:

void close();

It returns void, unfortunately. So, to know whether the closing was successful, use the member function:

bool is_open() const;

If the closing were successful, this would return zero, meaning the stream is no longer open. If the closing were unsuccessful, it would return 1 and meaning the stream could not be closed.

Output File Stream Operation

Now we will demonstrate opening a file and giving it new data content. To open an output stream with fsream, just use ios_base::out alone in the open() member function. The following program opens a file, and it sends the content of a string to it:

#include <fstream>
#include <iostream>
using namespace std;

int main() {

    fstream strm;
    strm.open("doc1.txt", ios_base::out);
    if (!strm.is_open()) {
        cout << "File could not be opened!" << endl;
        return 1;
    }

    char str[] = "A: This is the first line.\n"
                 "B: This is the second line.\n"
                 "C: This is the third line.\n";

    strm << str;
    strm.close();
    if (strm.is_open()){
        cout << "Stream could not close!" << endl;
        return 1;
    }
    cout << "Success, check file" << endl;
    return 0;
}

The name of the file is doc1.txt can include a full path or a relative path. The new content is identified by str in the program. At the end of the program, the string content would have been inserted into the stream and thus, the file with the statement:

strm << str;

Cout is a standard output object, and it is typically used for the console. It uses the extraction operator, << . The extraction operator is also used with file streams. The file stream object here is strm. The ‘\n’ character at the end of each quotation above is to ensure the next line appears below in the output file:

Instead of sending text to the file with the insertion operator, the write() member function can be used. The following code illustrates this:

basic_ostream<charT, traits>& write(const char_type* s, streamsize n)

Here is the full code with the write function used:

#include <fstream>
#include <iostream>
#include <cstring>
using namespace std;

int main() {

    fstream strm;
    strm.open("doc2.txt", ios_base::out);
    if (!strm.is_open()) {
        cout << "File could not be opened!" << endl;
        return 1;
    }

    char str[] = "A: This is the first line.\n"
                 "B: This is the second line.\n"
                 "C: This is the third line.\n";

    strm.write(str, strlen(str));

    strm.close();
    if (strm.is_open()){
        cout << "Stream could not close!" << endl;
        return 1;
    }

    return 0;
}

The first argument of the write() function is the identifier of the character array. The second argument is the number of characters (without \0) in the array.

Appending Characters to a File

To append text to a file, use “ios_base::app” alone, instead of “ios_base::out” in the open() member function. Still, use the insertion operator, <<, as follows:

#include <fstream>
#include <iostream>
#include <cstring>
using namespace std;

int main() {

    fstream strm;
    strm.open("doc2.txt", ios_base::app);
    if (!strm.is_open()) {
        cout << "File could not be opened!" << endl;
        return 1;
    }

    char str[] = "D: This is the fourth line.\n";

    strm << str;

    strm.close();
    if (strm.is_open()){
        cout << "Stream could not close!" << endl;
        return 1;
    }

    cout << "Success, check file" << endl;
    return 0;
}

The output file should now have four lines.

Input File Stream Operation

Now we will demonstrate reading a file character by character with fstream. To read a file with fstream, use ios_base::in as the flag in the open() member function. The following program reads all the content of the file and displays it at the console:

#include <fstream>
#include <iostream>
using namespace std;

int main()
{
    fstream strm;
    strm.open("doc1.txt", ios_base::in);
    if (!strm.is_open()) {
        cout << "Open file failed" << endl;
        return 1;
    }
    char c;

    while (!strm.eof()) {
        strm.get(c);
        cout << c;
    }

    strm.close();

    return 0;
}

The eof() is a member function, and it returns 1 when the end-of-file is reached and zero otherwise. The program reads the characters of the file, one by one, until the end-of-file is reached. It uses the get() member function, putting the read character into the variable c, which has already been declared. cout sends each character to the console. The output should be:

A: This is the first line.
B: This is the second line.
C: This is the third line.

Reading the Whole File With One Function

The whole file can be read using the member function:

basic_istream<charT, traits>& get(char_type* s, streamsize n, char_type delim);

It copies characters from the file and puts them into a character array. It does this until it meets the delimiter, EOF, or until it has copied the n – 1 character. It will fit the NULL (‘\0’) character as the last consecutive character in the array. This means the number of characters chosen for the array should be estimated to be at least the number of file characters (including any \n), plus one for the NULL character. It does not copy the delimiter character. The following code copies the whole file of doc1.txt, using this member function:

#include <fstream>
#include <iostream>
using namespace std;

int main()
{
    fstream strm;
    strm.open("doc1.txt", ios_base::in);
    if (!strm.is_open()) {
        cout << "Open file failed" << endl;
        return 1;
    }

    char arr[150];
    strm.get(arr, 150, EOF);
    strm.close();

    cout << arr << endl;
    return 0;
}

Reading Line by Line

The member function to use for reading from a file with fstream line by line is:

basic_istream<charT, traits>& getline(char_type* s, streamsize n, char_type delim);

It copies characters from the file and puts them into a character array. It does this until it meets the delimiter (e.g. ‘\n’) or until it has copied the n – 1 character. It will fit the NUL (‘\0’) character as the last consecutive character in the array. This means the number of characters chosen for the array should be estimated to be at least the number of visible characters, plus one for the null character. It does not copy the delimiter character. The following code copies the whole file of doc1.txt line by line, using this member function:

#include <fstream>
#include <iostream>
using namespace std;

int main()
{
    fstream strm;
    strm.open("doc1.txt", ios_base::in);
    if (!strm.is_open()) {
        cout << "Open file failed" << endl;
        return 1;
    }
    char arr[100];

    while (!strm.eof()) {
        strm.getline(arr, 100, '\n');
        cout << arr << endl;
    }

    strm.close();

    return 0;
}

Since ‘\n’ is not copied when copying a line, endl has to be used for the output display. Note that the number of characters in the array and streamsize variable, have been made the same. If it is known in advance that the delimiter is ‘\n’ then the following member function can be used:

basic_istream<charT, traits>& getline(char_type* s, streamsize n);

Seeking in the file

Characters including ‘\n’ have their natural positions in the file, beginning from 0, then 1, 2, 3, and so on. The seekg(pos) member function would point the pointer to the character of a position in the stream object. Then, get(c) can be used to obtain that character. The character in the 27th position of the current doc1.txt file is ‘B’. The following code reads and displays it:

#include <fstream>
#include <iostream>
using namespace std;

int main()
{
    fstream strm;
    strm.open("doc1.txt", ios_base::in);
    if (!strm.is_open()) {
        cout << "Open file failed" << endl;
        return 1;
    }
    char c;

    strm.seekg(27);
    strm.get(c);
    cout << c << endl;
    strm.close();

    return 0;
}

If the position given is greater than that of the last character in the file (minus 1), null is returned.

tellg() function

As a file is being read, an internal pointer points to the next character to be read. The tellg() member function can get the position number of the character the pointer is pointing to. When the file is just opened, tellg() will return 0 for the first character. After reading the first line, tellg() would return a number like 27 in the example below:

#include <fstream>
#include <iostream>
using namespace std;

int main()
{
    fstream strm;
    strm.open("doc1.txt", ios_base::in);
    if (!strm.is_open()) {
        cout << "Open file failed" << endl;
        return 1;
    }
    char arr[100];
    int pos;
    strm.getline(arr, 100, '\n');
    pos = strm.tellg();
    strm.close();

    cout << "Position in file is now: " << pos <<endl;


    return 0;
}

The output is:

~$ ./t9
Position in file is now: 27

The equivalent function for outputting is tellp().

seekdir

seekdir means seek direction. Its constants defined in the ios_base library are: beg for the beginning of the file, cur for the current position of the file, and end for ending of the file. The above seekg() function is overloaded for the input stream as:

basic_istream& seekg(off_type, ios_base::seekdir)

So, if the internal pointer is pointing to the character at position 27 by counting the beginning from 0, then

strm.seekg(0, ios_base::cur);

Will maintain the pointer at the current position.

strm.seekg(5, ios_base::cur);

Will take the pointer 5 places ahead to point at “i” in the second “This” of the doc1.txt file.

strm.seekg(-5, ios_base::cur);

Will take the pointer 5 places behind to point at “i” in the first “line” of the doc1.txt file. Note that the position of the newline character ‘\n’, which is not displayed at the output, is counted.

Now, no matter where the pointer might be,

strm.seekg(0, ios_base::beg);

Takes and maintains the pointer at the beginning of the file; to point to the first character of the file, with an offset of 0. In this case, it will point to “A”.

strm.seekg(5, ios_base::beg);

Will take the pointer to the beginning with an offset of 5 places ahead; point at “i” in the first “This” of the doc1.txt file. Note that the single space is counted as one character.

A negative integer in the offset position for “ios_base::beg” is not useful.

Well, no matter where the pointer might be,

strm.seekg(0, ios_base::end);

Will take and maintain the pointer just after the end of the file; to point to nothing.

A positive integer in the offset position for “ios_base::end” is not useful.

strm.seekg(-5, ios_base::end);

Will take the pointer to the end with an offset of 5 places behind; point at “i” in the last “line” of the doc1.txt file. Note that ‘\n’ and the dot are counted as one character each.

The following code illustrates the use of the function, at the current position, with a negative and positive offset:

#include <fstream>
#include <iostream>
using namespace std;

int main()
{
    fstream strm;
    strm.open("doc1.txt", ios_base::in);
    if (!strm.is_open()) {
        cout << "Open file failed" << endl;
        return 1;
    }

    char c;
    strm.seekg(27);
    strm.seekg(0, ios_base::cur);
    strm.get(c);
    cout << c << endl;

    strm.seekg(-5, ios_base::cur);
    strm.get(c);
    cout << c << endl;

    strm.seekg(+10, ios_base::cur);
    strm.get(c);

    strm.close();

    return 0;
}

The output is:

    B
    n

The get() member function shifts the pointer one place ahead after its execution.

The equivalent function for outputting is:

basic_ostream<charT, traits>& seekp(off_type, ios_base::seekdir)

Note the “p” in seekp for put, as opposed to “g” in seekg for get.

Conclusion

The fstream class deals with input from a file to a C++ program and output from the program to the file. In order to use the C++ fstream, an object from the class has to be instantiated. The stream object then has to be opened for input or output or both. To append text to the file, the stream has to be opened for appending. Make a habit of always closing the stream after it has been opened and used. If the file is an image file, then ios_base::binary will have to be ORed using | , with the second argument of the open() member function. This article hopefully assisted you in using the C++ fstream.

About the author

Chrysanthus Forcha

Discoverer of mathematics Integration from First Principles and related series. Master’s Degree in Technical Education, specializing in Electronics and Computer Software. BSc Electronics. I also have knowledge and experience at the Master’s level in Computing and Telecommunications. Out of 20,000 writers, I was the 37th best writer at devarticles.com. I have been working in these fields for more than 10 years.