File Input/Output Operations – in C++
Persistent Data storage in Files –File Input output streams
Chapter 4- File Input/Output Operations in C++
Chapter Objectives
The need for file I/O
I/O Stream class hierarchy
Creating file streams, connecting to and closing a file
Writing and reading a charter to file
Writing and Reading formatted text(sequential) files
File Stream pointers and their manipulations
Writing and reading binary files(Random Access files)
Chapter 4- File I/O Operations in C++
Why do we need Files?
All the programs we have looked at so far use input only from the
keyboard, and output only to the screen
o Data that is held in variables is temporary and is lost
when the program execution is finished
In order to store data permanently, we need to store it in files on the hard
disk
The easiest way to think about a file is as a linear sequence of characters
‘W’ ‘h’ ‘y’ ‘’ ‘d’ ‘o’ ….
with EoF marker
Chapter 4- File I/O Operations in C++
The Data Hierarchy
Chapter 4- File I/O Operations in C++
C++ Streams
Stream
A transfer of information in the form of a sequence of bytes
I/O Operations
Input stream: A stream that flows from an input device to the
main memory ( from: keyboard, disk drive, scanner or network
connection)
Output stream: A stream that flows from the main memory to an
output device ( to: screen, printer, disk drive or network
connection)
CHAPTER 4- FILE I/O OPERATIONS IN C++
The Interactive I/O Streams and your C++ Program
Program
Output Stream
Input Stream
(istream) (ostream)
I/O Devices
Chapter 4- File I/O Operations in C++
The File I/O Streams and your C++ Program
Program
Output Stream
Input Stream
(ifstream) (ofstream)
File on Disk
Chapter 4- File I/O Operations in C++
Hierarchy of the stream classes
ios
istream ostream
ifstream iostream ofstream
fstream
Chapter 4- File I/O Operations in C++
Headers required for stream processing
o <iostream.h> (cout, cin, cerr, clog)
o <fstream.h>
• class ifstream - input from file
• class ofstream – output to file
• class fstream - either input or output from/to file
Chapter 4- File I/O Operations in C++
Creating Streams
Before we can use an input or output stream in a program, we
must "create" it
//create an input stream
ifstream in_stream;
//create an output stream
ofstream out_stream;
Chapter 4- File I/O Operations in C++
Connecting Streams to Files
Having created a stream, we can
connect it to a file using the member
function "open(...)”
in_stream.open(“file.txt")
;
out_stream.open(“file.txt"
);
oit also deletes the previous contents of
the file
Chapter 4- File I/O Operations in C++
Creating and connecting streams to files in one statement
Other Ways to connect to a stream to a file.
ifstream in_stream(“file.txt”);
ofstream out_stream(“file.txt”);
Chapter 4- File I/O Operations in C++
Disconnecting Streams from Files
To disconnect a stream from a file, we can use the member function “close(...)”
in_stream.close();
out_stream.close();
o Adds an "end-of-file" marker at the end of
the file, so if no data has been output to
“file.txt” since "out_stream" was connected
to it, we have this situation
Chapter 4- File I/O Operations in C++
Checking for Failure with File Commands
void main()
{
ifstream in_stream;
in_stream.open("Lecture.txt");
if (in_stream.fail()) // or if(!in_stream)
{
cout << "Sorry, the file couldn't be opened!\n";
exit(1);
}
//....
}
Chapter 4- File I/O Operations in C++
Character Input
Input using get()
we can extract or read single characters from the file using the member function "get(...)“
in_stream.get(ch); has two effects:
o the variable "ch" is assigned the value "'4'", and
o the ifstream "in_stream" is re- positioned so as to be ready to input the next
character in the file.
o Diagrammatically, the new situation is:
Chapter 4- File I/O Operations in C++
Character Output
Output using put()
We can write single characters to a file opened via an
ofstream using the member function "put(...)“
out_stream.put('4'); changes the state to:
Chapter 4- File I/O Operations in C++
Checking for the end of an input file
The eof() function returns true if the end-of-file is
reached
This function can be used in a loop to determine how
many times the get() function should be called to read
the complete input file
Chapter 4- File I/O Operations in C++
Example
Write code to copy the contents (character by
character) of a file “old.txt” simultaneously to the
screen and to another file “new.txt”
Chapter 4- File I/O Operations in C++
#include <iostream>
#include <fstream>
using namespace std;
void main()
{
char character;
ifstream in_stream; //create input stream
ofstream out_stream; //create output stream
in_stream.open("old.txt"); //connect to file
if(!in_stream)//if file opening fails
{
cerr<<"file could not be opened";
exit(1);
}
out_stream.open("new.txt"); //connect to file
in_stream.get(character); //read 1 char from file
while (!in_stream.eof()) //loop till eof
{
cout << character; //display to screen
out_stream.put(character); //write to file
in_stream.get(character); //read next char
}
out_stream.close(); //disconnect stream
CHAPTER 4- FILE I/O OPERATIONS IN C++ in_stream.close(); //disconnect stream
}
Input and output using >>(read) and <<(write) a file
void main()
{
char character;
int number = 51;
int count = 0;
ofstream out_stream;
ifstream in_stream1;
ifstream in_stream2;
/* Create the file */
out_stream.open("Integers.txt");
for (count = 1 ; count <= 5 ; count++)
out_stream << number++ << ' ';
out_stream.close();
Chapter 4- File I/O Operations in C++
Input and output using >>(read) and <<(write) a file cont’d…
/* Count the integers in the file */
in_stream1.open("Integers.txt");
count = 0;
in_stream1 >> number;
while (!in_stream1.eof())
{
count++;
in_stream1 >> number;
}
in_stream1.close();
cout << "There are " << count << " integers in the file,\n";
Chapter 4- File I/O Operations in C++
Input and output using >> and <<
/* Count the non-blank characters */
in_stream2.open("Integers.txt");
count = 0;
in_stream2 >> character;
while (!in_stream2.eof())
{
count++;
in_stream2 >> character;
}
in_stream2.close();
cout << "represented using " << count << " characters.\n";
}
Chapter 4- File I/O Operations in C++
Input and output using >> and <<
Another Example
void main()
{
ofstream outClientFile( "clients.dat", ios::out );
if ( !outClientFile ) {
cerr << "File could not be opened”;
exit(1);
}
cout << "Enter the account, name, and balance.\n” << "Enter
end-of-file to end input.\n? ";
//contd on next slide…
Chapter 4- File I/O Operations in C++
Input and output using >> and <<
//…contd from previous slide
int account;
char name[30];
float balance;
while ( cin >> account >> name >> balance )
{
outClientFile << account << ' ' << name
<< ' ' << balance << '\n';
cout << "? ";
}
getch();
}
Chapter 4- File I/O Operations in C++
File open modes
ios:: app - (append) write all output to the end of file
ios:: ate - data can be written anywhere in the file
ios:: binary - read/write data in binary format
ios:: in - (input) open a file for input
ios::out - (output) open a file for output
ios:: trunc -(truncate) discard the files’ contents if it exists
ios::nocreate - if the file does NOT exist, the open operation fails
ios::noreplace - if the file exists, the open operation fails
Chapter 4- File I/O Operations in C++
File open modes (defaults)
class default open mode parameter
ofstream ios::out
ifstream ios::in
Chapter 4- File I/O Operations in C++
fstream class
An object of fstream opens a file for reading and writing simultaneously, so we can
write something like
fstream outClientFile;
int account; char name[30]; float balance;
outClientFile.open( "clients.dat",ios::out | ios::in );
//specifying multiple open modes
outClientFile>>account>>name>>balance;
cout<<account<<" "<<name<<" "<<balance;
outClientFile<<“writing something new!";
Chapter 4- File I/O Operations in C++
Reading and printing a sequential file
#include <iostream>
#include <fstream>
#include <iomanip>
Using namespace std;
void outputLine( int, const char *, double );
int main()
{
// ifstream constructor opens the file
ifstream inClientFile
(“E:\\MyFolder\\clients.dat", ios::in );
if ( !inClientFile ) {
cerr << "File could not be opened\n";
exit( 1 );
}
Chapter 4- File I/O Operations in C++
int account;
char name[ 30 ];
double balance;
cout << setiosflags( ios::left ) << setw(10) <<
"Account“ << setw( 13 ) << "Name"
<< "Balance\n";
while ( inClientFile >> account >> name >> balance )
outputLine( account, name, balance );
return 0; // ifstream destructor closes the file
}
void outputLine( int acct, const char *name, double bal )
{
cout << setiosflags( ios::left )<< setw(10) << acct <<
setw( 13 ) << name << setw( 7 ) << setprecision( 2 ) <<
resetiosflags( ios::left )<< setiosflags( ios::fixed |
CHAPTER 4- FILE I/O OPERATIONS IN C++
ios::showpoint )<< bal << '\n‘;}
Exercise
Design and implement a program that computes the average of a
sequence of numbers stored in a file
Chapter 4- File I/O Operations in C++
Algorithm
0. Prompt for input file name
1. Read name of input file from cin into inFileName
2. Open connection named fin to file named in inFileName
3. Initialize sum, count to zero.
4. Read a value from fin into number
5. Loop:
b. If no values left, terminate repetition.
c. Add number to sum.
d. Increment count.
End loop.
6. Close fin.
7. If count > 0: display sum / count.
Else display error message
End if
Chapter 4- File I/O Operations in C++
#include <iostream> // cin, cout, ...
#include <fstream> // ifstream, ofstream, ...
#include <string>
int main()
{
cout << “\nTo average the numbers in an input
file,enter the name of the file: “;
string inFileName;
cin >> inFileName;
ifstream fin(inFileName.data()); // open the
//connection
if(!fin)
{
cerr<<“File could not be opened”;
exit(1);
}
double number, sum = 0.0;
CHAPTER 4- FILE I/O OPERATIONS IN C++
// variables for
int count = 0; // computing //average
fin>>number; //read number
while(!fin.eof())
{
sum += number; // add it to sum
count++;
fin >> number; // read next number
}
fin.close(); // close fstream
if (count > 0)
cout << “\nThe average of the values in “
<< inFileName << “ is “ << sum/count << endl;
else
cout << “\n*** No values found in file “
CHAPTER 4- FILE I/O OPERATIONS IN C++ << inFileName << endl;
}
Four types functions to manipulate File Pointers
seekg()
seekp()
tellg()
tellp()
Chapter 4- File I/O Operations in C++
Repositioning the file-position pointer
<istream> and <ostream> classes provide member
functions for repositioning the file pointer (the byte
number of the next byte in the file to be read or to be
written.)
These member functions are:
o seekg (seek get) for istream class
o seekp (seek put) for ostream class
Chapter 4- File I/O Operations in C++
CHAPTER 4- FILE I/O OPERATIONS IN C++
Examples of moving a file pointer
fileObject.seekg( 0 );
o reposition the file-position pointer to the beginning of the file
(location 0) attached to fileObject
fileObject.seekg(n)
o position to the nth byte of fileObject (assumes ios::beg)
fileObject.seekg( n,ios::curr );
o position n bytes forward in fileObject
fileObject.seekg( n, ios::end );
o position n bytes back from end of fileObject
fileObject.seekg( 0, ios::end );
o position at end of fileObject
The same operations can be performed using ostream member
Chapter 4- File I/O Operations in C++
function seekp
Getting Current location of the file pointer
tellg() tell get and
tellp() tell put
Member functions tellg() and tellp() are provided to return the
current locations of the get and put pointers, respectively
long location = fileObject.tellg();
Chapter 4- File I/O Operations in C++
Problems with Sequential Files
Data that is formatted and written to a sequential file cannot be
modified easily without the risk of destroying other data in the file
o If we want to modify a record of data, the new data may be
longer than the old one and it could overwrite parts of the
record following it
Sequential files are inappropriate for so-called “instant access”
applications in which a particular record of information must be
located immediately.
These applications include banking systems, point-of-sale
systems, airline reservation systems, (or any data-base system)
Chapter 4- File I/O Operations in C++
Random Access Files
Instant access is possible with random access files
Individual records of a random access file can be accessed
directly (and quickly) without searching many other records
Chapter 4- File I/O Operations in C++
Binary I/O
We have seen examples of formatted I/O where each number is stored as
a sequence of characters but it is not always efficient
It is more efficient to use binary I/O in which numbers are stored in the
form of bytes
So, in binary I/O, an int is always stored in 4 bytes whereas its text
version might be 12345 which requires 5 bytes
For binary I/O
o the file should be opened in the binary mode (ios::binary)
o member functions read() of the ostream class and write() of the
istream class will be used for reading/writing data from/to disk
Chapter 4- File I/O Operations in C++
Writing Bytes with ostream Member Function write()
To write an int variable num to the file, use:
outFile.write( reinterpret_cast< const char * >(&num ), sizeof( num) );
OR
outFile.write((char *)& num , sizeof( num) );
This writes the binary version of the number’s 4 bytes
Function write treats its first argument as a group of bytes by viewing the object in
memory as a const char*, which is a pointer to a byte (remember that a char is one
byte)
Starting from that location, function “write” outputs the number of bytes specified
by its second argument, an integer of type size_t
Chapter 4- File I/O Operations in C++
reinterpret_cast
Unfortunately, most pointers that we pass to the function “write”
as the first argument are not of type const char *
To output objects of other types, we must convert the pointers to
those objects to type const char *
C++ provides the reinterpret_cast operator for cases like this in
which a pointer of one type must be cast to an unrelated pointer
type
o You can also use this cast operator to convert between
pointer and integer types, and vice versa
Chapter 4- File I/O Operations in C++
reinterpret_cast
A reinterpret_cast is performed at compile time and does not change the
value of the object to which its operand points
o Instead, it requests that the compiler reinterpret the operand as
the target type (specified in the angle brackets following the
keyword reinterpret_cast).
Here we are using a reinterpret cast to convert an int* (the type of the
expression &num) to a const char*
The same conversion would have to be done in case of the read() function
of the istream class
Chapter 4- File I/O Operations in C++
Example of a Program that Creates a Random Access File
//file: clientData.h
#include <string>
using namespace std;
struct clientData {
int accountNumber;
string lastName;
string firstName;
float balance;
};
Chapter 4- File I/O Operations in C++
// Creating a random access file
#include <iostream>
#include <fstream>
#include <stdlib>
#include "clientData.h"
void main()
{
ofstream outCredit ("credit.dat” , ios::binary);
if ( !outCredit ) {
cerr << "File could not be opened."
exit( 1 );
}
clientData blankClient = { 0, "", "", 0.0 };
for ( int i = 0; i < 100; i++ )
outCredit.write((const char*) &blankClient,
CHAPTER 4- FILE I/O OPERATIONS IN C++
sizeof( clientData ) );}
Writing data randomly to a random file
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include "clientData.h"
void main()
{
ofstream outCredit( "credit.dat",ios::ate|ios::binary );
if ( !outCredit ) {
cerr << "File could not be opened." << endl;
exit( 1 );
}
Chapter 4- File I/O Operations in C++
cout << "Enter account number”(1 to 100, 0 to end
input)\n? ";
clientData client;
cin >> client.accountNumber;
while ( client.accountNumber > 0 &&
client.accountNumber <= 100 ) {
cout << "Enter lastname, firstname, balance\n? ";
cin >> client.lastName >> client.firstName
>> client.balance;
outCredit.seekp( ( client.accountNumber - 1 )
*sizeof( clientData ) );
outCredit.write((const char*) &client ,
sizeof( clientData ) );
cout << "Enter account number\n? ";
cin >> client.accountNumber;
CHAPTER 4- FILE I/O OPERATIONS IN C++ }
Reading data from a random file sequentially
#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdlib.h>
#include “clientData.h"
void outputLine( ostream&, const clientData & );
void main()
{
ifstream inCredit( "credit.dat", ios::in );
if ( !inCredit ) {
cerr << "File could not be opened." << endl;
exit( 1 );
}
Chapter 4- File I/O Operations in C++
cout << setiosflags( ios::left ) << setw( 10 )
<< "Account” << setw( 16 ) << "Last Name"
<< setw( 11 )<< "First Name" <<
resetiosflags( ios::left ) << setw( 10 )
<< "Balance" << endl;
clientData client;
inCredit.read( (char*) &client,
sizeof( clientData ) );
while ( inCredit && !inCredit.eof() ) {
if ( client.accountNumber != 0 )
outputLine( cout, client );
inCredit.read( (char*) &client,
sizeof( clientData ) );
CHAPTER 4- FILE I/O OPERATIONS IN C++
}
}
void outputLine( ostream &output, const
clientData &c )
{
output << setiosflags( ios::left ) <<
setw( 10 ) << c.accountNumber <<
setw( 16 ) << c.lastName <<
setw( 11 ) << c.firstName <<
setw( 10 ) << setprecision( 2 ) <<
resetiosflags( ios::left )<<
setiosflags( ios::fixed | ios::showpoint )
<< c.balance << '\n';
}
CHAPTER 4- FILE I/O OPERATIONS IN C++
Updating a record using random access
void main()
{
fstream inFile ("credit.dat", ios::binary|ios::out|ios::in);
int accNumber;
cout<<"Enter the number of the account you wish to modify";
cin>>accNumber;
// move file-position pointer to correct record in file
inFile.seekg( ( accNumber - 1 ) * sizeof( clientData ) );
// read the required record from file
ClientData client;
inFile.read( (char*)&client, sizeof( clientData ) );
Chapter 4- File I/O Operations in C++
// update record
if ( client.accountNumber != 0 )
{
outputLine( cout, client ); // display the record
// request user to specify transaction
cout << "\nEnter charge(+)or payment(-):";
double transaction; // charge or payment
cin >> transaction;
client.balance += transaction;
outputLine( cout, client ); // display the
modified record
// move file-position pointer to correct record in
file
inFile.seekp( ( accNumber - 1 ) *
sizeof( ClientData ) );
CHAPTER 4- FILE I/O OPERATIONS IN C++
// write updated record over old record in file
inFile.write( (char*) &client,
sizeof( clientData ) ); }// end if
else {
// display error if account does not exist
cerr << "Account #" << accNumber
<< " has no information." << endl;
}
CHAPTER 4- FILE I/O OPERATIONS IN C++
Deleting a record from a random access file
void main() {
fstream deleteFromFile ("credit.dat", ios::binary|ios::out|
ios::in|ios::ate);
cout<<"Enter account number which is to be deleted";
int accNumber;
cin>>accNumber;
// move file-position pointer to correct record in file
deleteFromFile.seekg( ( accNumber - 1 ) *
sizeof(ClientData ) );
// read record from file
clientData client;
deleteFromFile.read( (char*) &client,sizeof( clientData ) );
Chapter 4- File I/O Operations in C++
// delete record, if record exists in file
if ( accNumber != 0 )
{
clientData blankClient = { 0, "noname ", "noname ",
0.0 }; // create blank record
// move file-position pointer to correct record in
file
deleteFromFile.seekp( ( accNumber - 1 ) *
sizeof( ClientData ) );
// replace existing record with blank record
deleteFromFile.write((char*) &blankClient,
sizeof( ClientData ) );
cout << "Account #" << accNumber << " deleted.\n";
}
else // display error if record does not exist
CHAPTER 4- FILE I/O OPERATIONS IN C++
cerr << "Account #" << accNumber << " is empty.\n";
}
Summary
The fstream library defines two classes:
o ifstream, for creating connections between programs and input files;
and
o ofstream, for creating connections between programs and output files.
Both ifstream and ofstream objects are created in a similar fashion.
Chapter 4- File I/O Operations in C++
Summary (contd)
If a string inFileName contains the name of an input file, and string outFileName
contains the name of an output file, then the statements
ifstream fin(inFileName.data());
ofstream fout(outFileName.data());
define fin and fout as connections to them.
Note that the string member function data() (or c_str()) must be used to
retrieve the actual characters of the file’s name
Chapter 4- File I/O Operations in C++
Summary (contd)
If a program tries to open an ifstream to a file that doesn’t exist,
the open is said to fail.
If a program tries to open an ofstream to a file that doesn’t
exist, the open operation creates a new, empty file for output
If a program tries to open an ofstream to a file that does exist,
the open operation (by default) empties that file of its contents,
creating a clean file for output
Chapter 4- File I/O Operations in C++
Summary (contd)
To open an existing file without emptying it, the value
ios_base::app can be given as a second argument:
ofstream
fout(outFileName.data(),ios::app);
Character string literals can also be used to create ifstream and
ofstream objects:
ofstream ferr(“error.log”);
Chapter 4- File I/O Operations in C++
Summary (contd)
Once an ifstream (or ofstream) has been opened, it can be read from using the usual
input (or output) operations:
o input: >>, get(), getline(), ...
o output: <<, put(), ...
In general, anything that can be done to an istream (or ostream) can be done to an
ifstream (or ofstream).
Chapter 4- File I/O Operations in C++
Summary (contd)
When the most recent input operation found no data remaining
in the file, the input operation is said to fail.
This can be detected using the ifstream function member
eof() (or fail()), which returns true if the last input
operation encountered the end of the file, and returns false
otherwise.
Chapter 4- File I/O Operations in C++
Summary (contd)
The eof() member function provides a convenient way
to build input loops that employ no redundant code
fin>> someValue
while(!fin.eof())
{
// ... process someValue
fin >> someValue;
}
Chapter 4- File I/O Operations in C++
Summary (contd)
Once we are done using an ifstream (or ofstream), it can
be closed using the close() function member:
o fin.close();
o fout.close();
Most systems limit the number of files a program can
have open simultaneously, so it is a good practice to
close a stream when you are finished using it.
Chapter 4- File I/O Operations in C++
Summary (contd)
To manipulate the read-position within an ifstream, the libraries provide these:
o tellg() // returns offset of current
read-position from
beginning of file
o seekg(offset, base) // move read-position
offset bytes from base
(one of ios::beg,
ios::cur, or
ios::end)
Chapter 4- File I/O Operations in C++
Summary (contd)
To manipulate the write-position within an ofstream, the libraries provide these:
o tellp() // returns offset of current
write-position from
beginning of file
o seekp(offset, base) // move write-position
offset bytes from base
(one of ios::beg,
ios::cur, or
ios::end)
Chapter 4- File I/O Operations in C++
Other Operations
To look at the next character in an ifstream without advancing the read-position (i.e.,
without reading it), the libraries provide:
o peek() // returns next char in the stream without reading it
To “unread” the last char that was read, the libraries provide:
o unget() // unread char most recently read
To skip a given number of chars in the stream (or until a particular char is
encountered), the libraries provide:
o ignore(n, stopChar) // skip past n chars,
or until stopChar
is encountered
Chapter 4- File I/O Operations in C++
Status Operations
To determine the status of a stream, the libraries provide these
function members:
o good() // returns true iff stream is ok
o bad() // returns true iff stream is not ok
o fail() // returns true iff last operation failed
o eof() // returns true iff last file-read failed
Chapter 4- File I/O Operations in C++