2. Stream Classes
A stream
is a general name given to a flow
of data.
A stream is represented by an object of a
particular class.
Example: cin and cout stream objects.
Different streams are used to represent
different kinds of data flow.
Example: ifstream class represent data
flow from input disk files.
3. The Stream Class Hierarchy
ios
istream
ifstream
ostream
iostream
fstream
ofstream
4. Formatted File I/O
In formatted I/O, numbers are stored on
disk as a series of characters.
This can be inefficient for numbers with
many digits.
However, it is easy to implement.
Characters and strings are stored more or
less normally.
6. Formatted File I/O
We created an object of ofstream and initialized
it to the file FDATA.TXT.
This initialization sets aside various resources
for the file, and accesses or opens the file of that
name on the disk.
If the file does not exist, it is created.
If it does exist, it is truncated and the new data
replaces the old.
The outfile object acts much as cout object.
So we can use the insertion operator (<<) to
output variables of any basic type to the file.
7. Formatted File I/O
When the program terminates, the outfile object goes out
of scope. This calls its destructor, which closes the file,
so we don’t need to close the file explicitly.
We must separate numbers with nonnumeric characters.
Strings must be separated with white spaces.
This implies that strings cannot contain imbedded
blanks.
Characters need no delimiters, since they have a fixed
length.
9. Strings with Embedded Blanks
To handle strings with embedded blanks, we need to
write a specific delimiter character after each string, and
use the getline() function, rather than the extraction
operator, to read them in.
This function reads characters, including white-space,
until it encounters the ‘n’ character, and places the
resulting string in the buffer supplied as an argument.
The maximum size of the buffer is given as the second
argument.
10. Strings with Embedded Blanks
int main()
{
ofstream outfile("test.txt");
outfile<< "I fear thee, ancient Mariner!n";
outfile<< "I fear thy skinny handn";
return 0;
}
11. Strings with Embedded Blanks
int main()
{
const int MAX=80;
char buffer[MAX];
ifstream infile("test.txt");
while(!infile.eof())
{
infile.getline(buffer,MAX);
cout<<buffer<<endl;
}
return 0;
}
12. Binary I/O
When storing large amount of data, it is more efficient to
use binary I/O.
In binary I/O, numbers are stored as they are in the
computer’s RAM memory, rather than as strings of
characters.
write(), a member of ofstream, and read(), a member of
ifstream are used.
These functions think about data in terms of bytes (type
char).
They don’t care how the data is formatted, they simply
transfer a buffer full of bytes from and to a disk file.
13. Binary I/O
The parameters to write() and read() are
the address of the data buffer and its
length.
The address must be cast, using
reinterpret_cast, to type char*, and the
length is the length in bytes (characters),
not the number of data items in the buffer.
14. Binary I/O
int main()
{
const int MAX=100;
int j;
int buff[MAX];
for(j=0; j<MAX; j++)
buff[j]=j;
ofstream os("test.dat",
ios::binary);
os.write(reinterpret_cast<cha
r*>(buff), MAX*sizeof(int));
os.close();
for(j=0; j<MAX; j++)
buff[j]=0;
ifstream is("test.dat",
ios::binary);
is.read(reinterpret_cast<char*
>(buff), MAX*sizeof(int));
for(j=0; j<MAX; j++){
if(buff[j]!=j)
{cerr<<"data is
incorrect"<<endl;}
}
cout<<"data is correct"<<endl;
return 0;
}
15. Binary I/O
We must use the ios::binary argument in the
second parameter to constructor when working
with binary data.
We need to use the reinterpret_cast operation to
make it possible for a buffer of type int to look to
the read() and write() functions like a buffer of
type char.
The reinterpret_cast operator is how we tell the
compiler. “I know you won’t like this, but I want
to do it anyway.”
It changes a section of memory without caring if
it makes sense.
16. Object I/O
We can also write objects, of user defined
classes, to files.
Similarly, we can read objects from files.
When writing an object we generally want
to use binary mode.
This writes the same bit configuration to disk
that was stored in memory
and ensures that numerical data contained in
objects is handled properly.
17. Example: Object I/O
#include<iostream>
using namespace std;
class Person
{
private:
char name[40];
int age;
public:
void readData()
{
cout<<"Enter name: ";
cin>>name;
cout<<"Enter age: ";
cin>>age;
}
void showData()
{
cout<<name<<endl
<<age<<endl;
}
};
18. Example: Object I/O
#include"person.h"
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main()
{
Person p;
p.readData();
ofstream os("person.dat",
ios::binary);
os.write(reinterpret_cast<char*
>(&p), sizeof(Person));
os.close();
Person p1;
ifstream is("person.dat",
ios::binary);
is.read(reinterpret_cast<char*>(
&p1), sizeof(Person));
p1.showData();
return 0;
}
19. I/O with Multiple Objects
int main() {
char ch;
Person p;
fstream file;
file.open("group.dat",ios::app | ios::out | ios::in | ios::binary);
do {
p.readData();
file.write(reinterpret_cast<char*>(&p), sizeof(Person));
cout<<"Enter another person(y/n)? : "<<endl;
cin>>ch;
}while(ch=='y');
20. I/O with Multiple Objects
file.seekg(0);//reset to start of file
file.read(reinterpret_cast<char*>(&p), sizeof(Person));
while(!file.eof())
{
cout<<"nPerson: ";
p.showData();
file.read(reinterpret_cast<char*>(&p), sizeof(Person));
}
return 0;
}
21. I/O with Multiple Objects
If we want to create a file stream object
that can be used for both, reading to and
writing from a file, we need to create an
object of fstream class.
open() function is a member of the
fstream class.
We can create a stream object once, and
can open it repeatedly.