UNIT-6
I/O System Basics, File I/O
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 −
|
To perform file processing in C++, header files <iostream> and <fstream> must be included in your C++ source 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.
|
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 );
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();
While doing C++ programming, you write information to a file from your program using the stream insertion operator (<<) just as you use that operator to output information to the screen. The only difference is that you use an ofstream or fstream object instead of the cout object.
You read information from a file into your program using the stream extraction operator (>>) just as you use that operator to input information from the keyboard. The only difference is that you use an ifstream or fstream object instead of the cin object.
Following is the C++ program which opens a file in reading and writing mode. After writing information entered by the user to a file named afile.dat, the program reads information from the file and outputs it onto the screen −
#include <fstream>
#include <iostream>
using namespace std;
int main () {
char data[100];
// open a file in write mode.
ofstream outfile;
outfile.open("afile.dat");
cout << "Writing to the file" << endl;
cout << "Enter your name: ";
cin.getline(data, 100);
// write inputted data into the file.
outfile << data << endl;
cout << "Enter your age: ";
cin >> data;
cin.ignore();
// again write inputted data into the file.
outfile << data << endl;
// close the opened file.
outfile.close();
// open a file in read mode.
ifstream infile;
infile.open("afile.dat");
cout << "Reading from the file" << endl;
infile >> data;
// write the data at the screen.
cout << data << endl;
// again read the data from the file and display it.
infile >> data;
cout << data << endl;
// close the opened file.
infile.close();
return 0;
}
When the above code is compiled and executed, it produces the following sample input and output −
$./a.out
Writing to the file
Enter your name: Zara
Enter your age: 9
Reading from the file
Zara
9
Above examples make use of additional functions from cin object, like getline() function to read the line from outside and ignore() function to ignore the extra characters left by previous read statement.
Both istream and ostream provide member functions for repositioning the file-position pointer. These member functions are seekg ("seek get") for istream and seekp ("seek put") for ostream.
The argument to seekg and seekp normally is a long integer. A second argument can be specified to indicate the seek direction. The seek direction can be ios::beg (the default) for positioning relative to the beginning of a stream, ios::cur for positioning relative to the current position in a stream or ios::end for positioning relative to the end of a stream.
The file-position pointer is an integer value that specifies the location in the file as a number of bytes from the file's starting location. Some examples of positioning the "get" file-position pointer are −
// position to the nth byte of fileObject (assumes ios::beg)
fileObject.seekg( n );
// position n bytes forward in fileObject
fileObject.seekg( n, ios::cur );
// position n bytes back from end of fileObject
fileObject.seekg( n, ios::end );
// position at end of fileObject
fileObject.seekg( 0, ios::end );
Key takeaway
- 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 −
In C++ stream refers to the stream of characters that are transferred between the program thread and i/o.
Stream classes in C++ are used to input and output operations on files and io devices. These classes have specific features and to handle input and output of the program.
The iostream.h library holds all the stream classes in the C++ programming language.
Let's see the hierarchy and learn about them,
Fig 1 - hierarchy
Now, let’s learn about the classes of the iostream library.
ios class − This class is the base class for all stream classes. The streams can be input or output streams. This class defines members that are independent of how the templates of the class are defined.
istream Class − The istream class handles the input stream in c++ programming language. These input stream objects are used to read and interpret the input as a sequence of characters. The cin handles the input.
ostream class − The ostream class handles the output stream in c++ programming language. These output stream objects are used to write data as a sequence of characters on the screen. cout and puts handle the out streams in c++ programming language.
OUT STREAM
COUT
#include <iostream>
using namespace std;
int main(){
cout<<"This output is printed on screen";
}
Output
This output is printed on screen
PUTS
#include <iostream>
using namespace std;
int main(){
puts("This output is printed using puts");
}
Output
This output is printed using puts
IN STREAM
CIN
#include <iostream>
using namespace std;
int main(){
int no;
cout<<"Enter a number ";
cin>>no;
cout<<"Number entered using cin is "<
Output
Enter a number 3453
Number entered using cin is 3453
gets
#include <iostream>
using namespace std;
int main(){
char ch[10];
puts("Enter a character array");
gets(ch);
puts("The character array entered using gets is : ");
puts(ch);
}
Output
Enter a character array
thdgf
The character array entered using gets is :
thdgf
Key takeaway
- In C++ stream refers to the stream of characters that are transferred between the program thread and i/o.
- Stream classes in C++ are used to input and output operations on files and io devices. These classes have specific features and to handle input and output of the program.
- The iostream.h library holds all the stream classes in the C++ programming language.
- The printed data with default setting by the I/O function of the language is known as unformatted data.
- It is the basic form of input/output and transfers the internal binary representation of the data directly between memory and the file.
- For example, in cin statement it asks for a number while executing. If the user enters a decimal number, the entered number is displayed using cout statement. There is no need to apply any external setting, by default the I/O function represents the number in decimal format.
- If the user needs to display a number in hexadecimal format, the data is represented with the manipulators are known as formatted data.
- It converts the internal binary representation of the data to ASCII characters which are written to the output file.
- It reads characters from the input file and coverts them to internal form.
- For example, cout<<hex<<13; converts decimal 13 to hexadecimal d. Formatting is a representation of data with different settings (like number format, field width, decimal points etc.) as per the requirement of the user.
- The iostream standard library provides cin and cout object.
- Input stream uses cin object for reading the data from standard input and Output stream uses cout object for displaying the data on the screen or writing to standard output.
- The cin and cout are pre-defined streams for input and output data.
Syntax:
cin>>variable_name;
cout<<variable_name; - The cin object uses extraction operator (>>) before a variable name while the cout object uses insertion operator (<<) before a variable name.
- The cin object is used to read the data through the input device like keyboard etc. while the cout object is used to perform console write operation.
Example: Program demonstrating cin and cout statements
#include<iostream>
using namespace std;
int main()
{
char sname[15];
cout<<"Enter Employee Name : "<<endl;
cin>>sname;
cout<<"Employee Name is : "<<sname;
return 0;
}
Output:
Enter Employee Name : Prajakta
Employee Name is : Prajakta
In the above example, cout<<"Employee Name is : "<<sname displays the contents of character array sname (student name). The cout statement is like printf statement as used in C language.
The cin statement cin>>sname reads the string through keyboard and stores in the array sname[15]. The cin statement is like scanf statement as used in C language. The endl is a manipulator that breaks a line.
Typecasting is a conversion of data in one basic type to another by applying external use of data type keywords.
Example: Program for Typecasting and displaying the converted values
#include<iostream>
using namespace std;
int main()
{
int i = 69;
float f = 4.5;
char c = 'D';
cout<<"Before Typecasting"<<endl;
cout<<"---------------------------------------------"<<endl;
cout<<"i = "<<i<<endl;
cout<<"f = "<<f<<endl;
cout<<"c = "<<c<<endl<<endl;
cout<<"After Typecasting"<<endl;
cout<<"--------------------------------------------"<<endl;
cout<<"Integer(int) in Character(char) Format : "<<(char)i<<endl;
cout<<"Float(float) in Integer(int) Format : "<<(int)f<<endl;
cout<<"Character(char) in Integer(int) Format : "<<(int)c<<endl;
return 0;
}
Output:
Before Typecasting
---------------------------------------------
i = 69
f = 4.5
c = D
After Typecasting
--------------------------------------------
Integer(int) in Character(char) Format : E
Float(float) in Integer(int) Format : 4
Character(char) in Integer(int) Format : 68
In the above example, the variables of integer(int), float(float) and character(char) are declared and initialized i = 69, f = 4.5, c = 'D'.
In first cout statement, integer value converted into character according to ASCII character set and the character E is displayed.
In second cout statement, float value is converted into integer format. The displayed value is 4 not 4.5, because while performing typecasting from float to integer, it removes decimal part of float value and considers only integer part.
In third cout statement, character converted into integer. The value of 'D' is 69, printed as an integer. The integer format converts character into integer.
Fig 2 – Typecasting Integer
In the above diagram, 69 is an integer value and it is converted into character E by using typecasting format (char).
Key takeaway
- If the user needs to display a number in hexadecimal format, the data is represented with the manipulators are known as formatted data.
- It converts the internal binary representation of the data to ASCII characters which are written to the output file.
- It reads characters from the input file and coverts them to internal form.
- For example, cout<<hex<<13; converts decimal 13 to hexadecimal d. Formatting is a representation of data with different settings (like number format, field width, decimal points etc.) as per the requirement of the user.
The C++ standard libraries provide an extensive set of input/output capabilities which we will see in subsequent chapters. This chapter will discuss very basic and most common I/O operations required for C++ programming.
C++ I/O occurs in streams, which are sequences of bytes. If bytes flow from a device like a keyboard, a disk drive, or a network connection etc. to main memory, this is called input operation and if bytes flow from main memory to a device like a display screen, a printer, a disk drive, or a network connection, etc., this is called output operation.
There are following header files important to C++ programs −
|
The Standard Output Stream (cout)
The predefined object cout is an instance of ostream class. The cout object is said to be "connected to" the standard output device, which usually is the display screen. The cout is used in conjunction with the stream insertion operator, which is written as << which are two less than signs as shown in the following example.
#include <iostream>
using namespace std;
int main() {
char str[] = "Hello C++";
cout << "Value of str is : " << str << endl;
}
When the above code is compiled and executed, it produces the following result −
Value of str is : Hello C++
The C++ compiler also determines the data type of variable to be output and selects the appropriate stream insertion operator to display the value. The << operator is overloaded to output data items of built-in types integer, float, double, strings and pointer values.
The insertion operator << may be used more than once in a single statement as shown above and endl is used to add a new-line at the end of the line.
The Standard Input Stream (cin)
The predefined object cin is an instance of istream class. The cin object is said to be attached to the standard input device, which usually is the keyboard. The cin is used in conjunction with the stream extraction operator, which is written as >> which are two greater than signs as shown in the following example.
#include <iostream>
using namespace std;
int main() {
char name[50];
cout << "Please enter your name: ";
cin >> name;
cout << "Your name is: " << name << endl;
}
When the above code is compiled and executed, it will prompt you to enter a name. You enter a value and then hit enter to see the following result −
Please enter your name: cplusplus
Your name is: cplusplus
The C++ compiler also determines the data type of the entered value and selects the appropriate stream extraction operator to extract the value and store it in the given variables.
The stream extraction operator >> may be used more than once in a single statement. To request more than one datum you can use the following −
cin >> name >> age;
This will be equivalent to the following two statements −
cin >> name;
cin >> age;
The Standard Error Stream (cerr)
The predefined object cerr is an instance of ostream class. The cerr object is said to be attached to the standard error device, which is also a display screen but the object cerr is un-buffered and each stream insertion to cerr causes its output to appear immediately.
The cerr is also used in conjunction with the stream insertion operator as shown in the following example.
#include <iostream>
using namespace std;
int main() {
char str[] = "Unable to read....";
cerr << "Error message : " << str << endl;
}
When the above code is compiled and executed, it produces the following result −
Error message : Unable to read....
The Standard Log Stream (clog)
The predefined object clog is an instance of ostream class. The clog object is said to be attached to the standard error device, which is also a display screen but the object clog is buffered. This means that each insertion to clog could cause its output to be held in a buffer until the buffer is filled or until the buffer is flushed.
The clog is also used in conjunction with the stream insertion operator as shown in the following example.
#include <iostream>
using namespace std;
int main() {
char str[] = "Unable to read....";
clog << "Error message : " << str << endl;
}
When the above code is compiled and executed, it produces the following result −
Error message : Unable to read....
You would not be able to see any difference in cout, cerr and clog with these small examples, but while writing and executing big programs the difference becomes obvious. So it is good practice to display error messages using cerr stream and while displaying other log messages then clog should be used.
Key takeaway
- The C++ standard libraries provide an extensive set of input/output capabilities which we will see in subsequent chapters. This chapter will discuss very basic and most common I/O operations required for C++ programming.
- C++ I/O occurs in streams, which are sequences of bytes. If bytes flow from a device like a keyboard, a disk drive, or a network connection etc. to main memory, this is called input operation and if bytes flow from main memory to a device like a display screen, a printer, a disk drive, or a network connection, etc., this is called output operation.
Stream Manipulators are functions specifically designed to be used in conjunction with the insertion (<<) and extraction (>>) operators on stream objects, for example −
std::cout << std::setw(10);
They are still regular functions and can also be called as any other function using a stream object as an argument, for example −
boolalpha (cout);
Manipulators are used to changing formatting parameters on streams and to insert or extract certain special characters.
Following are some of the most widely used C++ manipulators −
This manipulator has the same functionality as ‘\n’(newline character). But this also flushes the output stream.
#include<iostream>
int main() {
std::cout << "Hello" << std::endl << "World!";
}
Hello
World!
This manipulator controls whether decimal point is always included in the floating-point representation.
#include <iostream>
int main() {
std::cout << "1.0 with showpoint: " << std::showpoint << 1.0 << '\n'
<< "1.0 with noshowpoint: " << std::noshowpoint << 1.0 << '\n';
}
1.0 with showpoint: 1.00000
1.0 with noshowpoint: 1
This manipulator changes floating-point precision. When used in an expression out << setprecision(n) or in >> setprecision(n), sets the precision parameter of the stream out or into exactly n.
#include <iostream>
#include <iomanip>
int main() {
const long double pi = 3.141592653589793239;
std::cout << "default precision (6): " << pi << '\n'
<< "std::setprecision(10): " << std::setprecision(10) << pi << '\n';
}
default precision (6): 3.14159
std::setprecision(10): 3.141592654
This manipulator changes the width of the next input/output field. When used in an expression out << setw(n) or in >> setw(n), sets the width parameter of the stream out or in to exactly n.
#include <iostream>
#include <iomanip>
int main() {
std::cout << "no setw:" << 42 << '\n'
<< "setw(6):" << std::setw(6) << 42 << '\n'
<< "setw(6), several elements: " << 89 << std::setw(6) << 12 << 34 << '\n';
}
no setw:42
setw(6): 42
setw(6), several elements: 89 1234
Key takeaway
- Stream Manipulators are functions specifically designed to be used in conjunction with the insertion (<<) and extraction (>>) operators on stream objects, for example −
- std::cout << std::setw(10);
- They are still regular functions and can also be called as any other function using a stream object as an argument, for example −
- boolalpha (cout);
- Manipulators are used to changing formatting parameters on streams and to insert or extract certain special characters.
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:
|
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.
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
- 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:
|
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 :
Default Open Modes :
|
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.
Below is the implementation by using fstream class.
|
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.
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
Consider a situation, when we have two persons with the same name, Zara, in the same class. Whenever we need to differentiate them definitely we would have to use some additional information along with their name, like either the area, if they live in different area or their mother’s or father’s name, etc.
Same situation can arise in your C++ applications. For example, you might be writing some code that has a function called xyz() and there is another library available which is also having same function xyz(). Now the compiler has no way of knowing which version of xyz() function you are referring to within your code.
A namespace is designed to overcome this difficulty and is used as additional information to differentiate similar functions, classes, variables etc. with the same name available in different libraries. Using namespace, you can define the context in which names are defined. In essence, a namespace defines a scope.
A namespace definition begins with the keyword namespace followed by the namespace name as follows −
namespace namespace_name {
// code declarations
}
To call the namespace-enabled version of either function or variable, prepend (::) the namespace name as follows −
name::code; // code could be variable or function.
Let us see how namespace scope the entities including variable and functions −
#include <iostream>
using namespace std;
// first name space
namespace first_space {
void func() {
cout << "Inside first_space" << endl;
}
}
// second name space
namespace second_space {
void func() {
cout << "Inside second_space" << endl;
}
}
int main () {
// Calls function from first name space.
first_space::func();
// Calls function from second name space.
second_space::func();
return 0;
}
If we compile and run above code, this would produce the following result −
Inside first_space
Inside second_space
You can also avoid prepending of namespaces with the using namespace directive. This directive tells the compiler that the subsequent code is making use of names in the specified namespace. The namespace is thus implied for the following code −
#include <iostream>
using namespace std;
// first name space
namespace first_space {
void func() {
cout << "Inside first_space" << endl;
}
}
// second name space
namespace second_space {
void func() {
cout << "Inside second_space" << endl;
}
}
using namespace first_space;
int main () {
// This calls function from first name space.
func();
return 0;
}
If we compile and run above code, this would produce the following result −
Inside first_space
The ‘using’ directive can also be used to refer to a particular item within a namespace. For example, if the only part of the std namespace that you intend to use is cout, you can refer to it as follows −
using std::cout;
Subsequent code can refer to cout without prepending the namespace, but other items in the std namespace will still need to be explicit as follows −
#include <iostream>
using std::cout;
int main () {
cout << "std::endl is used with std!" << std::endl;
return 0;
}
If we compile and run above code, this would produce the following result −
std::endl is used with std!
Names introduced in a using directive obey normal scope rules. The name is visible from the point of the using directive to the end of the scope in which the directive is found. Entities with the same name defined in an outer scope are hidden.
A namespace can be defined in several parts and so a namespace is made up of the sum of its separately defined parts. The separate parts of a namespace can be spread over multiple files.
So, if one part of the namespace requires a name defined in another file, that name must still be declared. Writing a following namespace definition either defines a new namespace or adds new elements to an existing one −
namespace namespace_name {
// code declarations
}
Namespaces can be nested where you can define one namespace inside another name space as follows −
namespace namespace_name1 {
// code declarations
namespace namespace_name2 {
// code declarations
}
}
You can access members of nested namespace by using resolution operators as follows −
// to access members of namespace_name2
using namespace namespace_name1::namespace_name2;
// to access members of namespace:name1
using namespace namespace_name1;
In the above statements if you are using namespace_name1, then it will make elements of namespace_name2 available in the scope as follows −
#include <iostream>
using namespace std;
// first name space
namespace first_space {
void func() {
cout << "Inside first_space" << endl;
}
// second name space
namespace second_space {
void func() {
cout << "Inside second_space" << endl;
}
}
}
using namespace first_space::second_space;
int main () {
// This calls function from second name space.
func();
return 0;
}
If we compile and run above code, this would produce the following result −
Inside second_space
Key takeaway
- A namespace is designed to overcome this difficulty and is used as additional information to differentiate similar functions, classes, variables etc. with the same name available in different libraries. Using namespace, you can define the context in which names are defined. In essence, a namespace defines a scope.
REFERENCE
1 Object-Oriented Programming with C++ by E. Balaguruswamy. (Tata McGraw-Hill) 6th Edition and onwards
2. Object oriented Programming with C++- by SouravSahay (Oxford) 2ndedition