Startertutorials Blog
Tutorials and articles related to programming, computer science, technology and others.
Subscribe to Startertutorials.com's YouTube channel for different tutorial and lecture videos.

Categories: C++ Programming. No Comments on File Handling in C++ Programming

This article provides a comprehensive overview of file handling in C++ programming language along with example programs.

 

Introduction

A file is a collection of related data stored on a disk. It is advantageous to work with data stored in files rather than working with data given from keyboard due to following reasons:

  • It is difficult to read huge amount of data from keyboard.
  • Data entered from keyboard is volatile i.e., that data is cleared when power goes off.

 

File Handling Classes

 

Following figure illustrates the stream classes for working with files:

 

File Handling in C++ Programming - Class Hierarchy

 

fstreambase: The fstreambase is the base class for ifstream, ofstream, and fstream classes. Functions such are open() and close() are defined in this class.

 

fstream: It allows simultaneous input and output operations on filebuf. This class inherits istream and ostream classes. Member functions of the base classes istream and ostream starts the input and output.

 

ifstream: This class inherits both fstreambase and istream classes. It can access member functions such as get(), getline(), seekg(), tellg(), and read(). It allows input operations and provides open() with the default input mode.

 

ofstream: This class inherits both fstreambase and ostream classes. It can access member functions such as put(), seekp(), write(), and tellp(). It allows output operations and provides the open() function with the default output mode.

 

filebuf: The filebuf is used for input and output operations on files. This class inherits streambuf class. It also arranges memory for keeping input data and for sending output. The I/O functions of istream and ostream invoke the filebuf functions to perform the insertion and extraction on the streams.

 

Opening and Closing Files

 

For reading or writing data into files, the general operations are: open a connection to the file, read or write data to file, and close the connection to the file.

 

We can open a connection to the file in two ways: one way is by using the open() function and second way is by using the appropriate constructor.

 

Syntax for opening a connection to a file using open() function in input mode is as follows:

 

ifstream object-name;

object-name(“filename”);

 

In the above syntax, filename is the name of file from which you want to read the data. Syntax for opening a connection to a file using the constructor in input mode is as follows:

 

ifstream object-name(“filename”);

 

Syntax for opening a connection to a file using open() function in output mode is as follows:

 

ofstream object-name;

object-name(“filename”);

 

In the above syntax, filename is the name of file into which you want to write the data. Syntax for opening a connection to a file using the constructor in output mode is as follows:

 

ofstream object-name(“filename”);

 

After reading or writing data into file we can close the connection by writing the following:

 

object-name.close();

 

Reading and Writing into Files

 

After opening a connection to the file, reading and writing data to the file is an easy task. We can write data using the following syntax:

 

opfile<<data;

 

In the above syntax, opfile is the object of ofstream and data is any variable holding data. We can read data from a file using the following syntax:

 

ipfile>>data;

 

In the above syntax, ipfile is the object of ifstream and data is any variable into which the data is stored to process in the program.

 

Note: When a file is opened for writing data into it, if the specified file is not there, a new file with the same name is created and opened for output. If the file is already available, the old content in the file is cleared.

 

Following program demonstrates writing data into the file:

 

#include<iostream>
#include<fstream>
using namespace std;
int main()
{
	string name;
	int salary;
	cout<<"Enter name and salary: ";
	cin>>name>>salary;
	ofstream opfile("data.txt");	//Opening connection to a file using constructor
	opfile<<name<<"\t"<<salary;	//Writing data into file
	opfile.close();		//Closing connection to the file
	cout<<"Enter name and salary: ";
	cin>>name>>salary;
	ofstream newopfile;	
	newopfile.open("data.txt"); 	//Opening connection to a file using open() function
	newopfile<<name<<"\t"<<salary;	//Writing data into file
	newopfile.close();		//Closing connection to the file
	return 0;
}

Input for the above program is as follows:
Enter name and salary: suresh 7000
Enter name and salary: ramesh 8000

Output in the file "data.txt" is as follows:
ramesh	8000

 

Note: In the above program when the file is opened for the second time, the old data will be cleared.

 

Following program demonstrates reading data from a file:

 

#include<iostream>
#include<fstream>
using namespace std;
int main()
{
	string name;
	int salary;
	ifstream ipfile("data.txt");	//Opening connection to a file using constructor
	ipfile>>name>>salary;	//Reading data from file
	cout<<"Name is: "<<name<<endl;
	cout<<"Salary is: "<<salary;
	ipfile.close();		//Closing connection to the file	
	return 0;
}

Input from the file "data.txt" for above program is as follows:
ramesh		8000

Output for the above program is as follows:
Name is: ramesh
Salary is: 8000

 

Detecting End-of-File

 

While reading data from a file, if the file contains multiple rows, it is necessary to detect the end of file. This can be done using the eof() function of ios class. It returns 0 when there is data to be read and a non-zero value if there is no data.

 

Following program demonstrates writing and reading multiple rows of data into the file:

 

#include<iostream>
#include<fstream>
using namespace std;
int main()
{
	string name;
	int salary;
	ofstream opfile("data.txt");
	for(int i=1; i<=3; i++)
	{
		cout<<"Enter name and salary of employee "<<i<<":";
		cin>>name>>salary;
		opfile<<name<<"\t"<<salary;
	}
	opfile.close();
	cout<<"Data stored into file."<<endl;
	cout<<"Reading data from file..."<<endl;
	ifstream ipfile("data.txt");
	while(!ipfile.eof())    //Checking for end of file
	{
		ipfile>>name>>salary;
		cout<<"Name: "<<name<<" Salary: "<<salary<<endl;
	}
	ipfile.close();
	return 0;
}

Input and output for the above program is as follows:

Enter name and salary of employee 1:suresh 7000
Enter name and salary of employee 2:ramesh 8000
Enter name and salary of employee 3:mahesh 9000
Data stored into file.
Reading data from file...
Name: suresh Salary: 7000
Name: ramesh Salary: 8000
Name: mahesh Salary: 9000

 

File Modes

 

Until now when using the constructor or open() function for reading or writing data to a file, we are passing only one argument i.e., the file name. We can also pass a second argument which specifies the file mode.

 

The mode parameter specifies the mode in which the file has to be opened. We can specify one of the following modes available in ios file:

 

cpp-file-modes

 

A programmer can open a file in append mode by writing as follows:

 

fstream object-name(“filename”, ios::app);

 

A programmer can combine multiple modes using the | symbol as follows:

 

fstream object-name(“filename”, ios::out | ios::nocreate);

 

File Pointers and Manipulation

 

Every file will contain two pointers: a read pointer or also known as a get pointer and a write pointer also known as a put pointer. The read pointer or a get pointer is used to read data and the write pointer or put pointer is used to write data to a file. These pointers can be manipulated using the functions from stream classes. Those functions are as follows:

 

file-pointer-functions

 

The seekg() and seekp() functions specified above can be used to move the pointers in the file for random access. The syntax of these functions is as follows:

 

seekg(int offset, reference_position)

seekp(int offset, reference_position)

 

The offset is an integer parameter which specifies the position in bytes and reference_position can be any one of the following:

 

ios::beg (Moves the pointer from beginning of file)

ios::cur (Moves the pointer from current position of pointer)

ios::end (Moves the pointer from ending of file)

 

For example if we give seekg(20, ios::cur) moves the get pointer by 20 bytes from the current position. If we give seekg(-20, ios::end) moves the get pointer by 20 bytes back from the end of file.

 

Types of Files

 

C++ supports two types of files. They are text files and binary files.

 

ASCII Text Files

 

A text file is collection of characters that can be processed sequentially by a computer. As text files only process characters, they can read or write data one character at a time. In a text file, each line contains zero or more characters and ends with one or more characters that specify the end of a line.

 

In a text file data of all types are stored as a sequence of characters. Each file ends with a special character called as end of file marker.

 

Binary Files

 

A binary file is a file which contains any type of data, converted to binary format for computer storage and processing. A binary file is non-human readable. A binary file does not require any special processing of the data and each byte of data is transferred from the disk unprocessed. While text files can be processed sequentially, binary files can be processed sequentially or in a random fashion.

 

Binary files store data in internal representation format i.e., if we store an integer 51, it only occupies only one byte. Whereas in text file it occupies two bytes. One byte to store character 5 and another byte to store character 1.

 

Sequential and Random I/O

 

C++ allows data to be read or written from a file in sequential or random fashion. Reading data character by character or record by record is called sequential access. Reading data in any order is known as random access.

 

The fstream class provides functions like get(), read() for reading data and put(), write() for writing data to a file. The functions get() and put() are character-oriented functions. Syntax of these functions is as follows:

 

get(char)

put(char)

 

Following program demonstrates get() and put() functions:

 

#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
int main()
{
	char data[50], ch;
	cout<<"Enter a line of text: ";
	cin.getline(data, 50);
	fstream file("data.txt", ios::in | ios::out);
	int len = strlen(data);
	for(int i=0; i<len; i++)
	{
		file.put(data[i]);
	}
	file.seekg(0);
	for(int i=0; i<len; i++)
	{
		file.get(ch);
		cout<<ch;
	}
	file.close();
	return 0;
}

Input and output for the above program is as follows:

Enter a line of text: Welcome to file handling
Welcome to file handling

 

Until now we working with text files. But, as mentioned previously, reading and writing data in binary format is more efficient. We can store and retrieve objects in to binary files using read() and write() methods whose syntax is as follows:

 

read((char *)&var, sizeof(var));

write((char *)&var, sizeof(var));

 

Both functions accept to parameters. First parameter is the address of the variable or object and the second parameter is the size of variable or object. Following program demonstrates storing and retrieving an object from file:

 

#include<iostream>
#include<fstream>
using namespace std;
class Student
{
	private:
		int regdno;
		int marks;
	public:
		Student(){}
		Student(int no, int m)
		{
			regdno = no;
			marks = m;
		}
		void show()
		{
			cout<<"Regd.No. is: "<<regdno<<endl;
			cout<<"Marks are: "<<marks<<endl;
		}
};
int main()
{
	Student s1(501, 100);
	ofstream opfile("data.txt", ios::binary);
	opfile.write((char *)&s1, sizeof(s1));
	opfile.close();
	Student s2;
	ifstream ipfile("data.txt", ios::binary);
	ipfile.read((char *)&s2, sizeof(s2));
	ipfile.close();
	s2.show();
	return 0;
}

Output (in data.txt) for above program is as follows:

Regd.No. is: 501
Marks are: 100

 

Command Line Arguments

 

The data or parameters provided while invoking the program are known as command-line parameters or arguments. Command-line arguments can be accessed using the variables declared in the signature of main() function as shown below:

 

int main(int argc, char *argv[ ])

 

In the above syntax, first parameter argc holds the count of command-line arguments and the second parameter, an array of character pointers holds the actual command-line arguments.

 

Note: Remember that the first element in the array, i.e., argv[0] holds the filename. First command-line parameter will be available in argv[1], second parameter in argv[2] and so on.

 

Following program demonstrates working with command-line arguments:

#include<iostream>
#include<cstdlib>
using namespace std;
int main(int argc, char* argv[])
{
	cout<<"Arg count = "<<argc<<endl;
	int x = atoi(argv[1]);
	cout<<"First parameter = "<<x;
}

Input for the above program is: 10 20

Output for the above program is as follows:
Arg count = 3
First parameter = 10

 

 

How useful was this post?

Click on a star to rate it!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?

Suryateja Pericherla

Suryateja Pericherla, at present is a Research Scholar (full-time Ph.D.) in the Dept. of Computer Science & Systems Engineering at Andhra University, Visakhapatnam. Previously worked as an Associate Professor in the Dept. of CSE at Vishnu Institute of Technology, India.

He has 11+ years of teaching experience and is an individual researcher whose research interests are Cloud Computing, Internet of Things, Computer Security, Network Security and Blockchain.

He is a member of professional societies like IEEE, ACM, CSI and ISCA. He published several research papers which are indexed by SCIE, WoS, Scopus, Springer and others.

Leave a Reply

Your email address will not be published. Required fields are marked *