Unit 6
Working with files
In C++ Programming we are using the iostream standard library, it provides cin and cout methods for reading from input and writing to output respectively.
To read and write from a file we are using the standard C++ library called fstream. Let us see the data types define in fstream library is:
Data Type | Description |
Fstream | It is used to create files, write information to files, and read information from files. |
Ifstream | It is used to read information from files. |
Ofstream | It is used to create files and write information to the files. |
C++ FileStream example: writing to a file
Let's see the simple example of writing to a text file testout.txt using C++ FileStream programming.
- #include <iostream>
- #include <fstream>
- Using namespace std;
- Int main () {
- Ofstream filestream("testout.txt");
- If (filestream.is_open())
- {
- Filestream << "Welcome to javaTpoint.\n";
- Filestream << "C++ Tutorial.\n";
- Filestream.close();
- }
- Else cout <<"File opening is fail.";
- Return 0;
- }
Output:
The content of a text file testout.txt is set with the data:
Welcome to javaTpoint.
C++ Tutorial.
C++ FileStream example: reading from a file
Let's see the simple example of reading from a text file testout.txt using C++ FileStream programming.
- #include <iostream>
- #include <fstream>
- Using namespace std;
- Int main () {
- String srg;
- Ifstream filestream("testout.txt");
- If (filestream.is_open())
- {
- While ( getline (filestream,srg) )
- {
- Cout << srg <<endl;
- }
- Filestream.close();
- }
- Else {
- Cout << "File opening is fail."<<endl;
- }
- Return 0;
- }
Note: Before running the code a text file named as "testout.txt" is need to be created and the content of a text file is given below:
Welcome to javaTpoint.
C++ Tutorial.
Output:
Welcome to javaTpoint.
C++ Tutorial.
C++ Read and Write Example
Let's see the simple example of writing the data to a text file testout.txt and then reading the data from the file using C++ FileStream programming.
- #include <fstream>
- #include <iostream>
- Using namespace std;
- Int main () {
- Char input[75];
- Ofstream os;
- Os.open("testout.txt");
- Cout <<"Writing to a text file:" << endl;
- Cout << "Please Enter your name: ";
- Cin.getline(input, 100);
- Os << input << endl;
- Cout << "Please Enter your age: ";
- Cin >> input;
- Cin.ignore();
- Os << input << endl;
- Os.close();
- Ifstream is;
- String line;
- Is.open("testout.txt");
- Cout << "Reading from a text file:" << endl;
- While (getline (is,line))
- {
- Cout << line << endl;
- }
- Is.close();
- Return 0;
- }
Output:
Writing to a text file:
Please Enter your name: Nakul Jain
Please Enter your age: 22
Reading from a text file: Nakul Jain
22
KEY TAKEAWAY
In C++ Programming we are using the iostream standard library, it provides cin and cout methods for reading from input and writing to output respectively.
To read and write from a file we are using the standard C++ library called fstream. Let us see the data types define in fstream library is:
Data Type | Description |
Fstream | It is used to create files, write information to files, and read information from files. |
Ifstream | It is used to read information from files. |
Ofstream | It is used to create files and write information to the files. |
In C++, files are mainly dealt by using three classes fstream, ifstream, ofstream available in fstream headerfile.
ofstream: Stream class to write on files
ifstream: Stream class to read from files
fstream: Stream class to both read and write from/to files.
Now the first step to open the particular file for read or write operation. We can open file by
1. Passing file name in constructor at the time of object creation
2. Using the open method
For e.g.
Open File by using constructor
ifstream (const char* filename, ios_base::openmode mode = ios_base::in);
ifstream fin(filename, openmode) by default openmode = ios::in
ifstream fin(“filename”);
Open File by using open method
Calling of default constructor
ifstream fin;
Fin.open(filename, openmode)
fin.open(“filename”);
Modes :
Member Constant | Stands For | Access |
In * | Input | File open for reading: the internal stream buffer supports input operations. |
|
|
|
Out | Output | File open for writing: the internal stream buffer supports output operations. |
|
|
|
Binary | Binary | Operations are performed in binary mode rather than text. |
|
|
|
Ate | At end | The output position starts at the end of the file. |
|
|
|
App | Append | All output operations happen at the end of the file, appending to its existing contents. |
|
|
|
Trunc | Truncate | Any contents that existed in the file before it is open are discarded. |
|
|
|
Default Open Modes :
Ifstream | Ios::in |
Ofstream | Ios::out |
Fstream | Ios::in | ios::out |
Problem Statement : To read and write a File in C++.
Examples:
Input :
Welcome in GeeksforGeeks. Best way to learn things.
-1
Output :
Welcome in GeeksforGeeks. Best way to learn things.
Below is the implementation by using ifsream & ofstream classes.
/* File Handling with C++ using ifstream & ofstream class object*/ /* To write the Content in File*/ /* Then to read the content of file*/ #include <iostream>
/* fstream header file for ifstream, ofstream, Fstream classes */ #include <fstream>
Using namespace std;
// Driver Code Int main() { // Creation of ofstream class object Ofstream fout;
String line;
// by default ios::out mode, automatically deletes // the content of file. To append the content, open in ios:app // fout.open("sample.txt", ios::app) Fout.open("sample.txt");
// Execute a loop If file successfully opened While (fout) {
// Read a Line from standard input Getline(cin, line);
// Press -1 to exit If (line == "-1") Break;
// Write line in file Fout << line << endl; }
// Close the File Fout.close();
// Creation of ifstream class object to read the file Ifstream fin;
// by default open mode = ios::in mode Fin.open("sample.txt");
// Execute a loop until EOF (End of File) While (fin) {
// Read a Line from File Getline(fin, line);
// Print line in Console Cout << line << endl; }
// Close the file Fin.close();
Return 0; } |
Below is the implementation by using fstream class.
/* File Handling with C++ using fstream class object */ /* To write the Content in File */ /* Then to read the content of file*/ #include <iostream>
/* fstream header file for ifstream, ofstream, Fstream classes */ #include <fstream>
Using namespace std;
// Driver Code Int main() { // Creation of fstream class object Fstream fio;
String line;
// by default openmode = ios::in|ios::out mode // Automatically overwrites the content of file, To append // the content, open in ios:app // fio.open("sample.txt", ios::in|ios::out|ios::app) // ios::trunc mode delete all conetent before open Fio.open("sample.txt", ios::trunc | ios::out | ios::in);
// Execute a loop If file successfully Opened While (fio) {
// Read a Line from standard input Getline(cin, line);
// Press -1 to exit If (line == "-1") Break;
// Write line in file Fio << line << endl; }
// Execute a loop untill EOF (End of File) // point read pointer at beginning of file Fio.seekg(0, ios::beg);
While (fio) {
// Read a Line from File Getline(fio, line);
// Print line in Console Cout << line << endl; }
// Close the file Fio.close();
Return 0; } |
KEY TAKEAWAY
In C++, files are mainly dealt by using three classes fstream, ifstream, ofstream available in fstream headerfile.
ofstream: Stream class to write on files
ifstream: Stream class to read from files
fstream: Stream class to both read and write from/to files.
So far, we have been using the iostream standard library, which provides cin and cout methods for reading from standard input and writing to standard output respectively.
This tutorial will teach you how to read and write from a file. This requires another standard C++ library called fstream, which defines three new data types −
Sr.No | Data Type & Description |
1 | Ofstream This data type represents the output file stream and is used to create files and to write information to files. |
2 | Ifstream This data type represents the input file stream and is used to read information from files. |
3 | Fstream This data type represents the file stream generally, and has the capabilities of both ofstream and ifstream which means it can create files, write information to files, and read information from files. |
To perform file processing in C++, header files <iostream> and <fstream> must be included in your C++ source file.
Opening a File
A file must be opened before you can read from it or write to it. Either ofstream or fstream object may be used to open a file for writing. And ifstream object is used to open a file for reading purpose only.
Following is the standard syntax for open() function, which is a member of fstream, ifstream, and ofstream objects.
Void open(const char *filename, ios::openmode mode);
Here, the first argument specifies the name and location of the file to be opened and the second argument of the open() member function defines the mode in which the file should be opened.
Sr.No | Mode Flag & Description |
1 | Ios::app Append mode. All output to that file to be appended to the end. |
2 | Ios::ate Open a file for output and move the read/write control to the end of the file. |
3 | Ios::in Open a file for reading. |
4 | Ios::out Open a file for writing. |
5 | Ios::trunc If the file already exists, its contents will be truncated before opening the file. |
You can combine two or more of these values by ORing them together. For example if you want to open a file in write mode and want to truncate it in case that already exists, following will be the syntax −
Ofstream outfile;
Outfile.open("file.dat", ios::out | ios::trunc );
Similar way, you can open a file for reading and writing purpose as follows −
Fstream afile;
Afile.open("file.dat", ios::out | ios::in );
Closing a File
When a C++ program terminates it automatically flushes all the streams, release all the allocated memory and close all the opened files. But it is always a good practice that a programmer should close all the opened files before program termination.
Following is the standard syntax for close() function, which is a member of fstream, ifstream, and ofstream objects.
Void close();
KEY TAKEAWAY
We have been using the iostream standard library, which provides cin and cout methods for reading from standard input and writing to standard output respectively.
Description
It is used to check whether eofbit is set. This flag is set by all standard input operations when the End-of-File is reached in the sequence associated with the stream.
Declaration
Following is the declaration for eof() const function.
Bool eof() const;
Parameters
None
Return Value
True if the stream's eofbit error state flag is set (which signals that the End-of-File has been reached by the last input operation).
False otherwise.
Exceptions
Strong guarantee − if an exception is thrown, there are no changes in the stream.
Data Races
Accesses the stream object.
Concurrent access to the same stream object may cause data races.
Example
In below example explains about eof() const.
#include <iostream>
#include <fstream>
Int main () {
Std::ifstream is("example.txt");
Char c;
While (is.get(c))
Std::cout << c;
If (is.eof())
Std::cout << "[EoF reached]\n";
Else
Std::cout << "[error reading]\n";
Is.close();
Return 0;
}
KEY TAKEAWAY
Description
It is used to check whether eofbit is set. This flag is set by all standard input operations when the End-of-File is reached in the sequence associated with the stream.
This table shows the different modes in C++ that are possible when opening a file. However, you need to answer three basic questions every time you open a file:
- Do you want to read from the file or write to the file? Use ifstream to read and ofstream for writing. If you intend to both write to and read from the same file, use the fstream and set mode to in|out, but good luck — it’s much better to write to a file completely and then close it and reopen it for reading as a separate object.
- If you are writing to the file and it already exists, do you want to add to the existing contents (in which case, open with ate set) or truncate the file and start over (in which case use trunc)?
- Are you reading or writing text or binary data? Both ifstream and ofstream default to text mode. Use binary mode if you are reading or writing raw, non-text data.
Constants that Control How Files Are Opened | |
Flag | Meaning |
Ios_base::app | Seek to end-of-file before each write. |
Ios_base::ate | Seek to end-of-file immediately after opening the file, if it |
Ios_base::binary | Open file in binary mode (alternative is text mode). |
Ios_base::in | Open file for input (implied for istream). |
Ios_base::out | Open file for output (implied for ostream). |
Ios_base::trunc | Truncate file, if it exists (default for ostream). |
The primary difference between binary and text mode lies in the way that newlines are handled. The Unix operating system was written in the days when typewriters were still fashionable (when it was called “typing” instead of “keyboarding”). Unix ended sentences with a linefeed followed by a carriage return.
Subsequent operating systems saw no reason to continue using two characters to end a sentence, but they couldn’t agree on which character to use. Some use the carriage return, others used the linefeed, now renamed newline. The C++ standard is the single newline.
When a file is opened in text mode, the C++ library converts the single newline character into what is appropriate for your operating system on output, whether it’s a carriage return plus linefeed, a single carriage return, a linefeed, or something else entirely. It performs the opposite conversion while reading a file. The C++ library does no such conversions for a file opened in binary mode.
Always use binary mode when manipulating a file that’s not in human-readable format. Otherwise, if a byte in the data stream just happens to be the same as a carriage return or a linefeed, the file I/O library will modify it.
KEY TAKEAWAY
This table shows the different modes in C++ that are possible when opening a file. However, you need to answer three basic questions every time you open a file:
- Do you want to read from the file or write to the file? Use ifstream to read and ofstream for writing. If you intend to both write to and read from the same file, use the fstream and set mode to in|out, but good luck — it’s much better to write to a file completely and then close it and reopen it for reading as a separate object.
- If you are writing to the file and it already exists, do you want to add to the existing contents (in which case, open with ate set) or truncate the file and start over (in which case use trunc)?
- Are you reading or writing text or binary data? Both ifstream and ofstream default to text mode. Use binary mode if you are reading or writing raw, non-text data.
Function for manipulation of file pointer: – The C++ I/O system support for function for setting a file pointer to any desired position inside the file or to get the file pointer. These allow the programmer to have control over a pointer in the file where read or write operation text place. These for function are listed below.
Function | Member of class | Action performed |
Seekg() | Ifstream | Moves get file pointer to a specific location |
Seekp() | Ofstream | Moves put file pointer to a specific location |
Tellg() | Ifstream | Returns the current position of the get pointer |
Tellp() | Ofstream | Returns the current position of the put pointer |
The seekp() and tellp() are member function of ofstream. The seekg() or tellg() are member function of ifstream. The class fstream deals with file in both input and output modes. Hence, there are two file pointer in class fastream and the put pointer used for writing and get pointer used for the reading. Syntax of the seek function is –
<Stream Object>.seekg(long offset,seek_origin=ios::beg);
<Stream Object>.seekp(long offset,seek_origin=ios::beg
KEY TAKEAWAY
Function for manipulation of file pointer: – The C++ I/O system support for function for setting a file pointer to any desired position inside the file or to get the file pointer. These allow the programmer to have control over a pointer in the file where read or write operation text place.
Given a binary file that contains the records of students, the task is to modify or alter the record of the specified student. If the record of no such student exists, then print “record not found”.
Examples:
Input:
Old roll no: 1
New roll no: 11
New name: "Geek"
Output:
Roll no: 11
Name: "Geek"
Record successfully modified
Input:
Old roll no: 234
New roll no: 14
New name: "Geek2"
Output:
Record not found
In this example, the existing roll number of the student whose record is to be modified is taken from the user and a newly updated record is created that replaces the previous record.
Approach:
- Step 1: Searching for the roll number in the binary file.
- Step 2: While searching in the file, the variable “pos” stores the position of file pointer record then traverse(continue) reading of the record.
- Step 3: If the roll number to be searched exists then place the write pointer (to ending of the previous record) i.e. at pos.
- Step 4: Call getdata function to take the new record.
- Step 5: Write the new object at the position “pos” and hence the record is updated and print “record successfully updated”.
- Step 6: If the roll number does not exists then print “record not found”.
Standard Library Functions used:
// tells the position of read pointer
FILE.TELLG();
// places the writing pointer at
// position "pos" in the file
File.seekp(POS);
Below is the implementation of the above approach:
// C++ program to modify the content // of a binary file
#include <bits/stdc++.h> Using namespace std;
Class abc { Int roll; Char name[20];
Public: Void getdata(int, char[]); Void update(int, int, char[]); Void testcase1(); Void testcase2(); Void putdata(); };
// Code to display the data of the // data of the object Void abc::putdata() { Cout << "roll no: "; Cout << roll; Cout << "\nname: "; Cout << name; }
// Code to set the value to the object Void abc::getdata(int a, char str[]) { // setting the new roll no Roll = a;
// setting new name Strcpy(name, str); }
Void abc::update(int rno, int r, char str[]) { // code to update and modify // the content of the binary file Int pos, flag = 0;
// rno=9 Fstream fs; Fs.open("he.dat", Ios::in | ios::binary | ios::out);
While (!fs.eof()) { // storing the position of // current file pointeri.e. at // the end of previously read record Pos = fs.tellg();
Fs.read((char*)this, sizeof(abc)); If (fs) {
// comparing the roll no with that // of the entered roll number If (rno == roll) { Flag = 1;
// setting the new (modified ) // data of the object or new record Getdata(r, str);
// placing the put(writing) pointer // at the starting of the record Fs.seekp(pos);
// writing the object to the file Fs.write((char*)this, sizeof(abc));
// display the data Putdata(); Break; } } } Fs.close();
If (flag == 1) Cout << "\nrecord successfully modified \n"; Else Cout << "\nrecord not found \n"; }
// Sample input 1 Void abc::testcase1() { Int rno, r; Char name[20];
// roll no to be searched Rno = 1;
// new roll no r = 11;
// new name Strcpy(name, "Geek");
// call update function with new values Update(rno, r, name); }
// Sample input 2 Void abc::testcase2() { Int rno, r; Char name[20];
// roll no to be searched Rno = 4;
// new roll no r = 14;
// new name Strcpy(name, "Geek2");
// call update function with the new values Update(rno, r, name); }
// Driver code Int main() { Abc s;
// sample case 1 s.testcase1();
// sample case 2 s.testcase2();
Return 0; } |
KEY TAKEAWAY
Given a binary file that contains the records of students, the task is to modify or alter the record of the specified student. If the record of no such student exists, then print “record not found”.
Examples:
Input:
Old roll no: 1
New roll no: 11
New name: "Geek"
Output:
Roll no: 11
Name: "Geek"
Record successfully modified
Input:
Old roll no: 234
New roll no: 14
New name: "Geek2"
Output:
Record not found
In this example, the existing roll number of the student whose record is to be modified is taken from the user and a newly updated record is created that replaces the previous record.
Sometimes during file operations, errors may also creep in. For example, a file being opened for reading might not exist. Or a file name used for a new file may already exist. Or an attempt could be made to read past the end-of-file. Or such as invalid operation may be performed. There might not be enough space in the disk for storing data.
To check for such errors and to ensure smooth processing, C++ file streams inherit 'stream-state' members from the ios class that store the information on the status of a file that is being currently used. The current state of the I/O system is held in an integer, in which the following flags are encoded :
Name | Meaning |
Eofbit | 1 when end-of-file is encountered, 0 otherwise. |
Failbit | 1 when a non-fatal I/O error has occurred, 0 otherwise |
Badbit | 1 when a fatal I/O error has occurred, 0 otherwise |
Goodbit | 0 value |
C++ Error Handling Functions
There are several error handling functions supported by class ios that help you read and process the status recorded in a file stream.
Following table lists these error handling functions and their meaning :
Function | Meaning |
Int bad() | Returns a non-zero value if an invalid operation is attempted or any unrecoverable error has occurred. However, if it is zero (false value), it may be possible to recover from any other error reported and continue operations. |
Int eof() | Returns non-zero (true value) if end-of-file is encountered while reading; otherwise returns zero (false value). |
Int fail() | Returns non-zero (true) when an input or output operation has failed. |
Int good() | Returns non-zero (true) if no error has occurred. This means, all the above functions are false. For example, if fin.good() is true, everything is okay with the stream named as fin and we can proceed to perform I/O operations. When it returns zero, no further operations can be carried out. |
Clear() | Resets the error state so that further operations can be attempted. |
The above functions can be summarized as eof() returns true if eofbit is set; bad() returns true if badbit is set. The fail() function returns true if failbit is set; the good() returns true there are no errors. Otherwise, they return false.
These functions may be used in the appropriate places in a program to locate the status of a file stream and thereby take the necessary corrective measures. For example :
:
Ifstream fin;
Fin.open("master", ios::in);
While(!fin.fail())
{
: // process the file
}
If(fin.eof())
{
: // terminate the program
}
Else if(fin.bad())
{
: // report fatal error
}
Else
{
Fin.clear(); // clear error-state flags
:
}
:
C++ Error Handling Example
Here is an example program, illustrating error handling during file operations in a C++ program:
/* C++ Error Handling During File Operations
* This program demonstrates the concept of
* handling the errors during file operations
* in a C++ program */
#include<iostream.h>
#include<fstream.h>
#include<process.h>
#include<conio.h>
Void main()
{
Clrscr();
Char fname[20];
Cout<<"Enter file name: ";
Cin.getline(fname, 20);
Ifstream fin(fname, ios::in);
If(!fin)
{
Cout<<"Error in opening the file\n";
Cout<<"Press a key to exit...\n";
Getch();
Exit(1);
}
Int val1, val2;
Int res=0;
Char op;
Fin>>val1>>val2>>op;
Switch(op)
{
Case '+':
Res = val1 + val2;
Cout<<"\n"<<val1<<" + "<<val2<<" = "<<res;
Break;
Case '-':
Res = val1 - val2;
Cout<<"\n"<<val1<<" - "<<val2<<" = "<<res;
Break;
Case '*':
Res = val1 * val2;
Cout<<"\n"<<val1<<" * "<<val2<<" = "<<res;
Break;
Case '/':
If(val2==0)
{
Cout<<"\nDivide by Zero Error..!!\n";
Cout<<"\nPress any key to exit...\n";
Getch();
Exit(2);
}
Res = val1 / val2;
Cout<<"\n"<<val1<<" / "<<val2<<" = "<<res;
Break;
}
Fin.close();
Cout<<"\n\nPress any key to exit...\n";
Getch();
}
Let's suppose we have four files with the following names and data, shown in this table:
File Name | Data |
Myfile1.txt | 10 |
Myfile2.txt | 10 |
Myfile3.txt | 10 |
Myfile4.txt | 10 |
Now we are going to show the sample run of the above C++ program, on processing the files listed in the above table. Here are the four sample runs of the above C++ program, processing all the four files listed in the above table. Here is the sample output for the first file.
This output is for the second file
This is for the third file
This output produced, if the fourth file is processed.
KEY TAKEAWAY
Sometimes during file operations, errors may also creep in. For example, a file being opened for reading might not exist. Or a file name used for a new file may already exist. Or an attempt could be made to read past the end-of-file. Or such as invalid operation may be performed. There might not be enough space in the disk for storing data.
To check for such errors and to ensure smooth processing, C++ file streams inherit 'stream-state' members from the ios class that store the information on the status of a file that is being currently used. The current state of the I/O system is held in an integer, in which the following flags are encoded :
Name | Meaning |
Eofbit | 1 when end-of-file is encountered, 0 otherwise. |
Failbit | 1 when a non-fatal I/O error has occurred, 0 otherwise |
Badbit | 1 when a fatal I/O error has occurred, 0 otherwise |
Goodbit | 0 value |
References:
1. E Balagurusamy, “Programming with C++”, Tata McGraw Hill, 3rd Edition.
2. Herbert Schildt, “The Complete Reference C++”, 4th Edition.
3. Robert Lafore, “Object Oriented Programming in C++”, Sams Publishing, 4th Edition.
4. Matt Weisfeld, “The Object-Oriented Thought Process”, Pearson Education.