You are on page 1of 36

File I/O

<fstream> and File Classes

• <fstream> is the header that supports disk file


access.
• It defines classes like ifstream, ofstream, and
fstream.
Their class hierarchy looks like,
ios
ios

istream
istream ostream
ostream iostream
iostream

ifstream
ifstream ofstream
ofstream fstream
fstream
Opening and Closing a File

• Before any operation streams (objects)


should be created.

ifstream in; // input


ofstream out; // output
fstream io; // input and output
• Stream can be associated with a file is by using open() .

•Prototype:
void ifstream::open(const char *filename, ios::openmode mode = ios::in);
void ofstream::open(const char *filename, ios::openmode mode = ios::out | ios::trunc);
void fstream::open(const char *filename, ios::openmode mode = ios::in | ios::out);

• Filename -> name of file with/ without path


• Mode -> determined by openmode(enumeration), defined by
ios they are,

• These values can be combined.


• ios::app => appended to the end.

• ios::ate => seek to the end of the file

• ios::in => file is capable of input.

• ios::out => file is capable of output.

• ios::binary=>file opened in binary mode (default text mode).

• ios::trunc =>contents of any preexisting file is destroyed (in


ofstream)
• Files can be opened in two ways

ofstream out;
out.open("test", ios::out);
(Or)
out.open("test");

• Apart from these file streams have constructors that


automatically opens the file.

• Constructors have same parameters as open()


• Files should be checked whether it is open
before performing any operations
– It can be accomplished using is_open()
function.
– Prototype:
bool is_open( ); //returns true if file is open
eg:
if(!mystream.is_open())
{
cout << "File is not open.\n";
}
• Files can be closed using close() member
function.
mystream.close();
Reading and Writing Text Files

• << and >> operators can be used the


same way as with console I/O to read and
write to a file.

• Instead of predefined streams, file streams


should be used.
Example to write to a file
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ofstream out("INVNTRY"); // output, normal file
if(!out) {
cout << "Cannot open INVENTORY file.\n";
return 1;
}
out << "Radios " << 39.95 << endl;
out << "Toasters " << 19.95 << endl;
out << "Mixers " << 24.80 << endl;
out.close();
return 0;
}
Example to read from a file
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream in("INVNTRY"); // input
if(!in) {
cout << "Cannot open INVENTORY file.\n";
return 1;
}
char item[20];
float cost;
in >> item >> cost;
cout << item << " " << cost << "\n";
in >> item >> cost;
cout << item << " " << cost << "\n";
in >> item >> cost;
cout << item << " " << cost << "\n";
in.close();
return 0;
}
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ofstream out(“STRING”); // output, normal file
if(!out) {
cout << "Cannot open output file.\n";
return 1;
}
char str[80];
cout << "Write strings to disk. Enter ! to stop.\n";
do {
cout << ": ";
cin >> str; //reads from predefined stream
out << str << endl; // writes to disk file
} while (*str != '!');
out.close();
return 0;
}
• When using the >> operator, certain character
translations will occur.

• To avoid this file should be opened with binary


access.

• When inputting, if end-of-file is encountered, the


stream linked to that file will evaluate as false.
Unformatted and Binary I/O
• It is not always we work with text files.

• Situations might arise to access raw (binary) data.

• To perform binary operations file shud be opened with ios::binary


mode specifier.

• Unformatted file functions work with text mode also.


Characters vs. Bytes

• Earlier in C and C++, I/O was byte oriented.

• only types of streams available were char streams.

• With the advent of wide characters (type wchar_t) C++


I/O became character oriented.

• All of the streams used are char streams

• char stream establishes a one-to-one correspondence


between bytes and characters
put( ) and get( )
• Used to read and write unformatted data.

• They operate on characters.

• Prototype:
– istream &get(char &ch);
– ostream &put(char ch);

• The get() function reads a single character from the


invoking stream and puts that value in ch.

• The put() function writes ch to the stream


//program displays the contents of any file using get()
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char *argv[ ]) /* argc -> no of command line arguments
{ argv->argument in form of strings */
char ch;
if(argc!=2)
{
cout << "Usage: PR <filename>\n";
return 1;
}
ifstream in(argv[1], ios::in | ios::binary);
if(!in)
{
cout << "Cannot open file.";
return 1;
}
while(in) // in will be false when eof is reached
{
in.get(ch);
if(in) cout << ch;
}
return 0;
}
//program to write all characters from zero to 255 to a file using
put()

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int i;
ofstream out("CHARS", ios::out | ios::binary);
if(!out)
{
cout << "Cannot open output file.\n";
return 1;
}
// write all characters to disk
for(i=0; i<256; i++) out.put((char) i);
out.close();
return 0;
}
read( ) and write( )
• to read and write blocks of binary data use read() and
write() functions.

• Prototype:

– istream &read (char *buf, streamsize num);


– ostream &write (const char *buf, streamsize num);

• Num -> no of characters (to read/write)

• buf -> buffer to strore/retrieve data

• Streamsize -> integer type (holds the largest no of characters that


can be transferred in one I/O operation.)
#include <iostream> outbal.write((char *) &acc, sizeof(struct status));
#include <fstream> outbal.close();
#include <cstring> // now, read back;
using namespace std; ifstream inbal("balance", ios::in | ios::binary);
struct status { if(!inbal) {
char name[80]; cout << "Cannot open file.\n";
double balance; return 1;
unsigned long account_num; }
}; inbal.read((char *) &acc, sizeof(struct status));
cout << acc.name << endl;
int main() cout << "Account # " << acc.account_num;
{ cout.precision(2);
struct status acc; cout.setf(ios::fixed);
strcpy(acc.name, "Ralph Trantor"); cout << endl << "Balance: $" << acc.balance;
acc.balance = 1123.23; inbal.close();
acc.account_num = 34235678; return 0;
}
// write data
ofstream outbal("balance", ios::out | ios::binary);
if(!outbal) {
cout << "Cannot open file.\n";
return 1;
}
• Note:

• The buffer can be any type of object.

• a single call to read() or write() can read or write the


entire structure.

• The type casts are necessary when operating on a buffer


that is not defined as a character array.
• If no of chars in file < num only available characters are
moved to buffer.
• No of characters read can be found using,
streamsize gcount();
Usage:
stream. gcount(); //returns the no of bytes read
Random Access
• Files can be randomly accessed using, seekg() and
seekp()

• Prototype:
– istream &seekg(off_type offset, seekdir origin);
– ostream &seekp(off_type offset, seekdir origin);

• off_type -> integer type, contains the largest valid value.


• seekdir -> enumeration, determines how the seek will take place.
(they are defined in ios)
• It has two pointers associated with any file

get pointer ->specifies where in the file the next i/p operation will occur.

put pointer ->specifies where in the file the next o/p operation will
occur.

• These pointers automatically advance sequentially after any


i/o operation.

• seekg() and seekp() are used for non-sequential access.


• For the functions seekg(), seekp() offset number is one
of the value specified in origin,

• Starting from these positions the get/put pointers are


moved.

• Random-access I/O should be performed only on those


files opened for binary operations.
//to change a specific character in a file.
#include <iostream>
#include <fstream>
#include <cstdlib> /*Filename , number of the character in the file you want
using namespace std; to change, are given in command line */
int main(int argc, char *argv[])
{
if(argc!=4) {
cout << "Usage: CHANGE <filename> <character> <char>\n";
return 1;
}
fstream out(argv[1], ios::in | ios::out | ios::binary);
if(!out) {
cout << "Cannot open file.";
return 1;
} To execute:
out.seekp(atoi(argv[2]), ios::beg);
out.put(*argv[3]); change test 12 Z
out.close();
return 0;
} Prgm name filename offset char
// program to to reverse the first <num> for(i=0, j=e; i<j; i++, j--) {
characters in a file. inout.seekg(i, ios::beg);
#include <iostream> inout.get(c1);
#include <fstream> inout.seekg(j, ios::beg);
#include <cstdlib> inout.get(c2);
using namespace std; inout.seekp(i, ios::beg);
inout.put(c2);
int main(int argc, char *argv[]) inout.seekp(j, ios::beg);
{ inout.put(c1);
char ch; }
if(argc!=3) { inout.close();
cout << "Usage: SHOW <filename> <starting location>\n"; return 0;
return 1; }
}

fstream inout(argv[1], ios::in | ios::out | ios::binary);


if(!inout) { To execute:
cout << "Cannot open input file.\n";
return 1;
$ reverse test 10
} sample output:
long e, i, j; <before> This is a test.
char c1, c2;
e = atol(argv[2]); <after> a si sihTtest.
Obtaining the Current File Position

• the current position of each file pointer can be determined


using,
– pos_type tellg( );
– pos_type tellp( );

• pos_type, defined by ios largest value that either function


can return.

• Can be used as arguments to seekg() and seekp(),


– istream &seekg(pos_type pos);
– ostream &seekp(pos_type pos);
I/O Status
• The I/O system maintains status info about the outcome
of each I/O operation.
• It is held in an object of type iostate(enumeration)
• I/O status can be obtained using two ways

1. iostate rdstate( );
2. Any one of the foll functions can be used,
• bool bad( );
• bool eof( );
• bool fail( );
• bool good( );

• Once an error has occurred, it may need to be cleared


before your program continues.( use clear() func)

• Prototype:
– void clear(iostate flags=ios::goodbit);
#include <iostream> void checkstatus(ifstream &in)
#include <fstream> {
using namespace std; ios::iostate i;
void checkstatus(ifstream &in); i = in.rdstate();
int main(int argc, char *argv[]) if(i & ios::eofbit)
{ cout << "EOF encountered\n";
if(argc!=2) { else if(i & ios::failbit)
cout << "Usage: Display <filename>\n"; cout << "Non-Fatal I/O error\n";
return 1; else if(i & ios::badbit)
} cout << "Fatal I/O error\n";
ifstream in(argv[1]); }
if(!in) {
cout << "Cannot open input file.\n";
return 1;
}
char c;
while(in.get(c)) {
if(in) cout << c;
checkstatus(in);
}
checkstatus(in); // check final status
in.close();
return 0;
}
Customized I/O and Files
• Since the stream operations/functions are
similar, the same inserters & extractors
used for console I/O operations can be
used for files also.
#include <iostream> // Display name and phone number.
#include <fstream> ostream &operator<<(ostream &stream, phonebook o)
#include <cstring> {
using namespace std; stream << o.name << " ";
stream << "(" << o.areacode << ") ";
class phonebook stream << o.prefix << "-";
{ stream << o.num << "\n";
char name[80]; return stream; // must return stream
char areacode[4]; }
char prefix[4];
char num[5]; // Input name and telephone number.
istream &operator>>(istream &stream, phonebook &o)
public: {
phonebook() { }; cout << "Enter name: ";
phonebook(char *n, char *a, char *p, char *nm) stream >> o.name;
{ cout << "Enter area code: ";
strcpy(name, n); stream >> o.areacode;
strcpy(areacode, a); cout << "Enter prefix: ";
strcpy(prefix, p); stream >> o.prefix;
strcpy(num, nm); cout << "Enter number: ";
} stream >> o.num;
cout << "\n";
friend ostream &operator<<(ostream &stream, return stream;
phonebook o); }
friend istream &operator>>(istream &stream,
phonebook &o);
};
int main()
switch(c) {
{
case '1':
phonebook a;
cin >> a;
char c; cout << "Entry is: ";
fstream pb("phone", ios::in | ios::out | ios::app); cout << a; // show on screen
if(!pb) pb << a; // write to disk
{ break;
cout << "Cannot open phone book file.\n"; case '2':
return 1; char ch;
} pb.seekg(0, ios::beg);
for(;;) while(!pb.eof())
{ {
do pb.get(ch);
if(!pb.eof()) cout << ch;
{
}
cout << "1. Enter numbers\n";
pb.clear(); // reset eof
cout << "2. Display numbers\n";
cout << endl;
cout << "3. Quit\n";
break;
cout << "\nEnter a choice: ";
cin >> c;
case '3':
pb.close();
} while(c<'1' || c>'3');
return 0;
}
}
}
• The overloaded << operator can be used
to write to a disk file or to the screen
without any changes.

You might also like