File Management
File Management
File Management
File Management
File handling is an important part of all programs. Most of
the applications will have their own features to save some
data to the local disk and read data from the disk again.
Files which are on the secondary storage device are called
physical files. In order to process file through program,
logical file must be created on the RAM. This logical file is
nothing but an object having file data type. As an object
there should be a variable identifier that points to it. This
variable is called file variable and sometimes also called
file handler. C++ File I/O classes simplify such file
read/write operations for the programmer by providing
easier to use classes.
-1-
6.1.1.1. Streams
The C++ file system is designed to work with a wide
variety of devices, including terminals, disk drives, and
tape drives. Even though each device is very different, the
C++ file system transforms each into a logical device called
stream. There are two types of streams: text and binary.
a. Text Streams
A text stream is a sequence of characters. In a text stream,
certain character translations may occur as required by the
host environment. For example a new line may be
converted to a carriage return/linefeed pair. There may not
be a one-to-one relationship between the characters that are
written (or read) and those on the external device. Because
of possible transformations, the number of characters
written (or read) may not be the same as those on the
external device.
b. Binary streams
A binary stream is a sequence of bytes with a one-to-one
correspondence to those in the external device i.e., no
character translations occur. The number of bytes written
(or read) is the same as the number on the external device.
-2-
However, an implementation-defined number of null bytes
may be appended to a binary stream. These null bytes
might be used to pad the information so that it fills a sector
on a disk, for example.
6.1.1.2. Files
In C++, a file can be anything from a disk file to a terminal
or printer. You associate a stream with a specific file by
performing an open operation. Once a file is open,
information can be exchanged between it and a program.
All streams are the same but all files are not. If the file can
support position requests, opening that file also initializes
the file position indicator to the start of the file. As each
character is read from or written to the file, the position
indicator is incremented. You disassociate a file from a
specific stream with a close operation. If you close a file
opened for output, then contents, if any, of its associated
stream are written to the external device. This process is
referred to as flushing the stream. All files are closed
automatically when the program terminates normally. Files
are not closed when a program terminates abnormally.
Each stream that is associated with a file has a file control
-3-
structure of type FILE. This structure FILE is defined in
the header stdio.h.
The File Pointer
A file pointer is a pointer to information that defines
various things about the file, including its name, status, and
the current t position of the file. In essence, the file pointer
identifies a specific disk file and is used by the associated
stream to direct the operation of the I/O functions. A file
pointer is a pointer variable of type FILE.
FILE * fp;
-4-
6.1.1.4. C++ File I/O Classes and Functions
To perform file I/O, the header file fstream.h is requied.
fstream.h defines several classes, including ifstream,
ofstream, and fstream. These classes are derived form
istream and ostream, repectively. istream and ostream are
derived form ios.
Three file I/O classes are used for File Read/Write
operations:
a. ifstream - Can be used for File read/input
operations
b. ofstream - Can be used for File write/output
operations
c. fstream - Can be used for both read/write c++ file
I/O operations
These classes are derived directly or indirectly from the
classes istream, and ostream. We have already used objects
whose types were these classes: cin is an object of class
istream and cout is an object of class ostream. Therefore,
we have already been using classes that are related to our
file streams. And in fact, we can use our file streams the
same way we are already used to use cin and cout, with the
-5-
only difference that we have to associate these streams with
physical files. Let's see an example:
-6-
The first byte holds the character with ASCII value equals
to one and the second byte a character with ASCII value
equals 65 which is ‘A’. Then if you open the binary file
you will see these characters in place of 321.
-7-
will be performing both input and output operations must
be declared as class fstream.
ifstream in ; //input stream
ofstream out ; // output stream
fstream io ; // input and output
Once you have declared a stream, you associate it with a
file by using the method open().
The method open ( ) is a member of each of the three
stream classes. Its prototype is:
void open (const char *filename, int mode, int access =
filebuf::penprot );
Where:
Filename is the name of the file.
The value of the mode determines how the file is opened. It
must be one (or more) of these values:
Mode Description
ios::app Write all output to the end of the file
ios::ate Open a file for output and move to the end
of the file (normally used to append data
to a file). Data can be written anywhere in
-8-
the file.
ios::binary Cause the file to be opened in binary
mode.
ios::in Open a file for input
ios::nocreate If the file does not exist, the open
operation fails.
ios::noreplac If the file exists, the open operation fails.
e
ios::out Open a file for output
ios:trunc Discard the file's content if it exists (this is
also the default action ios::out)
-9-
fstream myStream;
myStream.open ( "test", ios::in |
ios::out );
If open ( ) fails, myStrream will
be zero
if (myStream){
cout << "Cannot open a file.\n";
// handle error
}
Each one of the open() member functions of the classes
ofstream, ifstream and fstream has a default mode that is
used if the file is opened without a second argument:
class default mode parameter
ofstreamios::out
ifstream ios::in
fstream ios::in | ios::out
For ifstream and ofstream classes, ios::in and ios::out are
automatically and respectively assumed, even if a mode
that does not include them is passed as second argument to
the open() member function. The default value is only
applied if the function is called without specifying any
value for the mode parameter. If the function is called with
- 10 -
any value in that parameter the default mode is overridden,
not combined.
File streams opened in binary mode perform input and
output operations independently of any format
considerations. Non-binary files are known as text files,
and some translations may occur due to formatting of some
special characters (like newline and carriage return
characters).
Since the first task that is performed on a file stream object
is generally to open a file, these three classes include a
constructor that automatically calls the open() member
function and has the exact same parameters as this member.
Therefore, we could also have declared the previous myfile
object and conducted the same opening operation in our
previous example by writing:
ofstream myfile ("example.bin",
ios::out | ios::app | ios::binary);
Combining object construction and stream opening in a
single statement. Both forms to open a file are valid and
equivalent.
- 11 -
To check if a file stream was successful opening a file, you
can do it by calling to member is_open() with no
arguments. This member function returns a bool value of
true in the case that indeed the stream object is associated
with an open file, or false otherwise:
if (myfile.is_open()) { /* ok,
proceed with output */ }
ifstream myStream
( "myfile" ); // open file for
input
When we are finished with our input and output operations
on a file we shall close it so that its resources become
available again. In order to do that we have to call the
stream's member function close(). This member function
takes no parameters, and what it does is to flush the
associated buffers and close the file:
myfile.close();
Once this member function is called, the stream object can
be used to open another file, and the file is available again
to be opened by other processes.
- 12 -
In case that an object is destructed while still associated
with an open file, the destructor automatically calls the
member function close(). The close method takes no
parameters and returns no value.
- 13 -
myfile << "Writing this to a
file.\n";
myfile.close();
return 0;
}
This code creates a file called example.txt and inserts a
sentence into it in the same way we are used to do with
cout, but using the file stream myfile instead.
Example 2: writing on a text file
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ofstream myfile ("example.txt");
if (myfile.is_open())
{
myfile << "This is a line.\n";
myfile << "This is another line.\n";
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
Example 3: reading a text file
#include <iostream>
- 14 -
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("example.txt");
if (myfile.is_open())
{
while (! myfile.eof() )
{
getline (myfile,line);
cout << line << endl;
}
myfile.close();
}
return 0;
}
This last example reads a text file and prints out its content
on the screen. Notice how we have used a new member
function, called eof() that returns true in the case that the
end of the file has been reached. We have created a while
loop that finishes when indeed myfile.eof() becomes true
(i.e., the end of the file has been reached).
Checking state flags
- 15 -
In addition to eof(), which checks if the end of file has been
reached, other member functions exist to check the state of
a stream (all of them return a bool value):
Function Description
bad() Returns true if a reading or writing operation
fails. For example in the case that we try to
write to a file that is not open for writing or if
the device where we try to write has no space
left.
fail() Returns true in the same cases as bad(), but
also in the case that a format error happens,
like when an alphabetical character is extracted
when we are trying to read an integer number.
eof() Returns true if a file open for reading has
reached the end.
good() It is the most generic state flag: it returns false
in the same cases in which calling any of the
previous functions would return true.
In order to reset the state flags checked by any of these
member functions we have just seen we can use the
member function clear(), which takes no parameters.
- 16 -
get and put stream pointers
All I/O streams objects have, at least, one internal stream
pointer:
ifstream, like istream, has a pointer known as the get
pointer that points to the element to be read in the next
input operation.
ofstream, like ostream, has a pointer known as the put
pointer that points to the location where the next
element has to be written.
Finally, fstream, inherits both, the get and the put
pointers, from iostream (which is itself derived from
both istream and ostream).
These internal stream pointers that point to the reading or
writing locations within a stream can be manipulated using
the following member functions:
tellg() and tellp()
These two member functions have no parameters and return
a value of the member type pos_type, which is an integer
data type representing the current position of the get stream
pointer (in the case of tellg) or the put stream pointer (in the
case of tellp).
- 17 -
seekg() and seekp()
These functions allow us to change the position of the get
and put stream pointers. Both functions are overloaded with
two different prototypes. The first prototype is:
seekg ( position );
seekp ( position );
Using this prototype the stream pointer is changed to the
absolute position position (counting from the beginning of
the file). The type for this parameter is the same as the one
returned by functions tellg and tellp: the member type
pos_type, which is an integer value.
The other prototype for these functions is:
seekg ( offset, direction );
seekp ( offset, direction );
Using this prototype, the position of the get or put pointer is
set to an offset value relative to some specific point
determined by the parameter direction. offset is of the
member type off_type, which is also an integer type. And
direction is of type seekdir, which is an enumerated type
(enum) that determines the point from where offset is
- 18 -
counted from, and that can take any of the following
values:
ios::be
offset counted from the beginning of the stream
g
offset counted from the current position of the
ios::cur
stream pointer
ios::en
offset counted from the end of the stream
d
The following example uses the member functions we have
just seen to obtain the size of a file:
Example: obtaining file size
#include <iostream>
#include <fstream>
using namespace std;
int main () {
long begin,end;
ifstream myfile ("example.txt");
begin = myfile.tellg();
myfile.seekg (0, ios::end);
end = myfile.tellg();
myfile.close();
cout << "size is: " << (end-begin) <<
" bytes.\n";
return 0;
}
- 19 -
6.1.4. Binary File processing
In binary files, to input and output data with the extraction
and insertion operators (<< and >>) and functions like
getline is not efficient, since we do not need to format any
data, and data may not use the separation codes used by
text files to separate elements (like space, newline, etc...).
File streams include two member functions specifically
designed to input and output binary data sequentially: write
and read. The first one (write) is a member function of
ostream inherited by ofstream. And read is a member
function of istream that is inherited by ifstream. Objects of
class fstream have both members. Their prototypes are:
- 20 -
There are two ways to write and read binary data to and
from a file.
get ( ) and put ( )
read ( ) and write ( )
If you will be performing binary operations on a file, be
sure to open it using the ios::binary mode specifier.
- 21 -
}
while (in) //inn will be 0 when
eof is reached
{ in.get ( ch );
cout << ch;
}
When the end-of-file is reached, the stream associated with
the file becomes zero.
ofstream out ( "chars", io::out |
ios::binary);
for (int i= 0; i < 256; i++)
out.put ( (char ) i ) ; //write
all characters to disk
out.close ( );
6.1.4.2. read ( ) and write ( )
The read ( ) method reads num bytes from the associated
stream, and puts them in a memory buffer (pointed to by
buf).
istream & read ( unsigned char *
buf, int num );
The write ( ) method writes num bytes to the associated
stream from the memory buffer (pointed to by buf).
ostream & write ( const unsigned
char * buf, int num );
If the end-of-file is reached before num characters have
been read, then read ( ) simply stops, and the buffer
- 22 -
contains as many characters as were available. You can
find out how many characters have been read by using
another member function, called gcount ( ), which has the
prototype:
int gcount ( );
6.1.4.3. More get ( ) functions
The method get ( ) is overloaded in several ways.
a. int get ( )
It returns the next character from the stream. It returns EOF
if the end of file is encountered.
b. getline ( )
- 23 -
istream & getline ( char *buf, int
num, char delim ='\n');
This method is virtually identical to the get ( buf, num,
delim) version of get ( ). The difference is getline ( ) reads
and removes the delimiter from the input stream.
ifstream::pos_type size;
char * memblock;
int main () {
ifstream file ("example.txt", ios::in|
ios::binary|ios::ate);
if (file.is_open())
{
size = file.tellg();
memblock = new char [size];
file.seekg (0, ios::beg);
file.read (memblock, size);
file.close();
delete[] memblock;
- 24 -
}
else cout << "Unable to open file";
return 0;
}
In this example the entire file is read and stored in a
memory block. Let's examine how this is done:
First, the file is open with the ios::ate flag, which means
that the get pointer will be positioned at the end of the file.
This way, when we call to member tellg(), we will directly
obtain the size of the file. Notice the type we have used to
declare variable size:
ifstream::pos_type size;
ifstream::pos_type is a specific type used for buffer and file
positioning and is the type returned by file.tellg(). This type
is defined as an integer type, therefore we can conduct on it
the same operations we conduct on any other integer value,
and can safely be converted to another integer type large
enough to contain the size of the file. For a file with a size
under 2GB we could use int:
int size;
size = (int) file.tellg();
- 25 -
Once we have obtained the size of the file, we request the
allocation of a memory block large enough to hold the
entire file:
memblock = new char[size];
Right after that, we proceed to set the get pointer at the
beginning of the file (remember that we opened the file
with this pointer at the end), then read the entire file, and
finally close it:
file.seekg (0, ios::beg);
file.read (memblock, size);
file.close();
At this point we could operate with the data obtained from
the file. Our program simply announces that the content of
the file is in memory and then terminates.
Function Description
Detecting EOF It returns nonzero when the end of the
int eof ( ); file has been reached; otherwise it
returns zero.
Reading and discarding Reads and discards characters until
characters from the either num characters have been
- 26 -
input stream. nignored (1 by default ) or until the
istream & ignore (int charcter specified by delim is
num = 1, int delim = encounterdd (EOF by default). If the
EOF); delimiting character is encountered, it
is not removed from the input stream.
Obtain the next One can obtain the next character in
character in the input the input stream without removing it
stream without from that stream by using peek ( ). It
removing it from that returns the next character in the
stream stream or EOF if the end of file is
int peek ( ); encountered.
istream & putback One can return the last character read
( char c); from a stream to that stream using
putback ( ).
- 27 -
ostream & flush ( ); full. Only then are the contents of that
buffer written to disk. However, you
can force the information to be
physically written to the disk before
the buffer is full by calling flush ( ).
- 28 -
pointer, which specifies where in the file the next output
operation will occur. Each time an input or output operation
takes place the appropriate pointer is automatically
sequentially advanced. The seekg ( ) method moves the
associated file's current get pointer offset number of bytes
from the specified origin, which must be one of three
values. The seekp ( ) method moves the associated file's
current put pointer offset number of bytes from the
specified origin, which must be one of three values.
- 29 -
system is held in an integer, in which the following flags
are encoded.
int rdstate ( );
rdstate function returns the current status of the error flags
encoded into an integer. It returns zero, when no error has
occurred. Otherwise, an error bit is turned on.
Method Description
int bad Returns true if badbit is set.
()
- 30 -
int fail Returns true if failbit is set.
()
int eof Returns true if there are no errors.
()
int good Otherwise they return false.
()
Once an error has occurred, it may need to be cleared
before your program continues. to do this, use the clear ( )
method.
- 31 -
Instead of that, the character is inserted in that stream's
intermediate buffer.
- 32 -
parameters, causes an immediate synchronization.
This function returns an int value equal to -1 if the
stream has no associated buffer or in case of failure.
Otherwise (if the stream buffer was successfully
synchronized) it returns 0.
- 33 -
- 34 -