streams -...
TRANSCRIPT
UNIT – V
FILE HANDLING CONTENTS:
� Streams and formatted I/O � I/O manipulators � File handling � Random access � Object serialization � Namespaces � Std namespace � ANSI String Objects � Standard template library
Streams:
� A stream is an object where a program can either insert or extract characters to or from
it. The standard input and output stream objects of C++ are declared in the header file
iostream.
� A steam is a sequence of bytes. It acts either as a source from which the input data can
be obtained or as a destination to which the output data can be sent.
� The source stream that provides the data to the program is called the input stream and
the destination stream that receives output from the program is called the output stream.
� All streams behave in the same way even though the actual physical devices they are
connected to may differ substantially.
� Because all streams behave the same, the same I/O functions can operate on virtually
any type of physical device.
� For example, you can use the same function that writes to a file to write to the printer or
to the screen. The advantage to this approach is that you need learn only one I/O
system. C++ STEAMS
i/p stream
Exception from i/p stream i/p streams
i/p device
Program
o/p device
The C++ Stream Classes:
� Standard C++ provides support for its I/O system in <iostream>. The C++ I/O system
is built upon two related but different template class hierarchies.
� The first is derived from the low-level I/O class called basic_streambuf. This class
supplies the basic, low-level input and output operations, and provides the underlying
support for the entire C++ I/O system.
� The class hierarchy that you will most commonly be working with is derived from
basic_ios. This is a high-level I/O class that provides formatting, error checking, and
status information related to stream I/O.
� (A base class for basic_ios is called ios_base, which defines several nontemplate traits
used by basic_ios.) basic_ios is used as a base for several derived classes, including
basic_istream, basic_ostream, and basic_iostream.
� These classes are used to create streams capable of input, output, and input/output,
respectively.
C++’s Predefined Streams:
� When a C++ program begins execution, four built-in streams are automatically opened.
They are:
Stream Meaning Default Device cin Standard input Keyboard
cout Standard output Screen
cerr Standard error output Screen
clog Buffered version of cerr Screen
� Streams cin, cout, and cerr correspond to C’s stdin, stdout, and stderr.
� By default, the standard streams are used to communicate with the console.
Formatted I/O: � The C++ I/O system allows you to format I/O operations. For example, you can set a
field width, specify a number base, or determine how many digits after the decimal
point will be displayed.
� There are two related but conceptually different ways that you can format data. First,
you can directly access members of the ios class.
� Specifically, you can set various format status flags defined inside the ios class or call
various ios member functions.
� Second, you can use special functions called manipulators that can be included as part
of an I/O expression.
Formatting Using the ios Members:
� When the left flag is set, output is left justified.
� When right is set, output is right justified.
� When the internal flag is set, a numeric value is padded to fill a field by inserting
spaces between any sign or base character.
� If none of these flags are set, output is right justified by default.
Eg:
#include <iostrearn>
using narnespace std;
int main()
cout.setf(ios: :showpoint)
cout.setf(ios: :showpos)
cout << 100,0; // displays +100.0
return 0;
� It is important to understand that setf( ) is a member function of the ios class and
affects streams created by that class.
� Therefore, any call to setf( ) is done relative to a specific.
� Instead of making multiple calls to setf( ), you can simply OR together the values of
the flags you want set.
� For example, this single call accomplishes the same thing:
/ / You can OR together two or more flags cout.setf(ios: :showpoint, ios: :showpos)
� Because the format flags are defined within the ios class, you must access their values
by using ios and the scope resolution operator.
� For example, showbase by itself will not be recognized. You must specify
ios::showbase.
Clearing Format Flags: � The complement of setf( ) is unsetf( ).
� This member function of ios is used to clear one or more format flags.
� The flags specified by flags are cleared. (All other flags are unaffected.) The previous
flag settings are returned.
Using width( ), precision( ), and fill( ):
� In addition to the formatting flags, there are three member functions defined by ios that
set these format parameters: the field width, the precision, and the fill character.
� The functions that do these things are width( ), precision( ), and fill( ), respectively.
� By default, when a value is output, it occupies only as much space as the number of
characters it takes to display it.
� However, you can specify a minimum field width by using the width() function. Its
prototype is shown here:
streamsize width(streamsize w);
� Here,w becomes the field width, and the previous field width is returned.
� In some implementations, the field width must be set before each output. If it isn’t, the
default field width is used.
� The streamsize type is defined as some form of integer by the compiler.
� After you set a minimum field width, when a value uses less than the specified width,
the field will be padded with the current fill character (space, by default) to reach the
field width.
� If the size of the value exceeds the minimum field width, the field will be overrun. No
values are truncated.
� When outputting floating-point values, you can determine the number of digits to be
displayed after the decimal point by using the precision() function.
� Its prototype is shown here:
streamsize precision(streamsize p);
Examples: Cout.width(5);
Cout<<543;
Will produce the following width Cout.precision(3);
Cout.3.1111;
Will produce
3.111(truncated)
Cout.fill(‘*’);
Cout.width(5);
Cout<<456;
Will produce Cout.setf(ios::showpoint);
Cout.setf(ios::showpos);
Cout.precision(3);
Cout.width(5);
Cout<<1.2;
I/O Manipulators: Using Manipulators to Format I/O:
� The second way you can alter the format parameters of a stream is through the use of
special functions called manipulators that can be included in an I/O expression.
5 4 3
* * 4 5 6
+ 1 . 2 0
Manipulator Purpose Input/Output Endl Output a newline character Output
ends Output a null. Output
internal Turns on internal flag. Output
left Turns on left flag. Output
noshowpoint Turns off showpoint flag. Output
noshowpos Turns off showpos flag. Output
nouppercase Turns off uppercase flag. Output
resetiosfiags Turn off the flags Input/Output
right Turns on right flag. Output
setfill(int ch) Set the fill character Output
setiosflags Turn on the flags Input/output
setprecision Set the number of digits Output
setw(int w) Set the field width to w . Output
showbase Turns on showbase flag Output
showpoint Turns on showpoint flag. Output
showpos Turns on showpos flag. Output
� Here is an example that uses some manipulators: #include <iostrearm
#include <iomanip> using narnespace std;
int main()
cout << setfill(’?’) << setw(10) ;
cout << 100 << endl;
This displays ???????100
� As the examples suggest, the main advantage of using manipulators instead of the ios
member functions is that they commonly allow more compact code to be written.
� You can use the setiosflags() manipulator to directly set the various format flags
related to a stream. For example, this program uses setiosflags() to set the showbase
and showpos flags:
#include <iostrearn>
#include <lomanip>
int main()
cout << setiosflags(ios showpos);
cout << setiosflags(ios showbase);
cout << 123 ;
return 0;
� The manipulator setiosflags( ) performs the same function as the member function setf 0.
Designing our own manipulators:
� The general form of creating a manipulator without argument is ostream & manipulator (ostream & output, arguments-if-any) { ………….. …………….(code) …………… return output; }
� The following function defines a manipulator called unit that displays inches ostream & unit(ostream & output) { output<<”inches”; return output; } The statement cout<<36<<unit; Will produce the following output: 36 inches
File Handling: C++ File I/OL: File Classes:
� To perform file I/O, you must include the header <fstream> in your program.
� It defines several classes, including ifstream, ofstream, and fstream.
� These classes are derived from istream, ostream, and iostream, respectively.
� Remember, istream, ostream, and iostream are derived from ios, so ifstream,
ofstream, and fstream also have access to all operations defined by ios .
� Another class used by the file system is filebuf, which provides low-level facilities
to manage a file stream.
The File Pointer:
� The file pointer is the common thread that unites the C I/O system.
� A file pointer is a pointer to a structure of type FILE. It points to information that
defines various things about the file, including its name, status, and the current position
of the file.
� In essence, the file pointer identifies a specific file and is used by the associated
stream to direct the operation of the I/O functions.
� In order to read or write files, your program needs to use file pointers. To obtain a file
pointer variable, use a statement like this:
FILE *fp Opening and Closing a File:
� In C++, you open a file by linking it to a stream. Before you can open a file, you must
first obtain a stream.
� There are three types of streams: input, output, and input/output. To create an input
stream, you must declare the stream to be of class if stream.
� To create an output stream, you must declare it as class ofstream. Streams that will be
performing both input and output operations must be declared as class fstream.
� For example, this fragment creates one input stream, one output stream, and one
stream capable of both input and output:
if stream in; // input
of stream out; // output
fstrearn io; // input and output
� Once you have created a stream, one way to associate it with a file is by using openO.
This function is a member of each of the three stream classes.
� The prototype for each is shown here:
void ifstream::open(const char *fi1ename ,ios::openmode mode= ios::in);
void ofstream::open(const char *fi1ename, ios::openmode mode =ios::out |ios::trunc);
void fstream::open(const char *filename, ios::openmode mode = ios::in | ios::out);
� Here, filename is the name of the file; it can include a path specifier.
� The value of mode determines how the file is opened.
� It must be one or more of the following values defined by open mode, which is an
enumeration defined by ios (through its base class los_base).
ios::app
ios::ate
ios::binary
ios::in
ios::out
ios::trunk
� You can combine two or more of these values by ORing them together. Including
ios::app causes all output to that file to be appended to the end.
� This value can be used only with files capable of output.
� Including ios::ate causes a seek to the end of the file to occur when the file is opened.
� Although ios::ate causes an initial seek to end-of-file, I/O operations can still occur
anywhere within the file.
� The ios::in value specifies that the file is capable of input.
� The ios::out value specifies that the file is capable of output.
� The ios::binary value causes a file to be opened in binary mode.
� By default, all files are opened in text mode. In text mode, various character
translations may take place, such as carriage return/linefeed sequences being converted
into new lines.
� However, when a file is opened in binary mode, no such character translations will
occur.
� Understand that any file, whether it contains formatted text or raw data, can be opened
in either binary or text mode.
� When creating an output stream using ofstream, any preexisting file by that name is
automatically truncated.
� The following fragment opens a normal output file. ofstream out;
out.open(”test”, ios::out);
� For ifstream, mode defaults to ios::in; for ofstream, and for fstream, it is ios::in I
ios::out. Therefore, the preceding statement will usually look like this:
Out.open( test ) ;// defaults to output and normal file
� If open() fails, the stream will evaluate to false when used in a Boolean expression.
� Therefore, before using a file, you should test to make sure that the open operation
succeeded.
� Although it is entirely proper to open a file by using the open() function, most of the
time you will not do so because the ifstream, ofstream, and fstream classes have
constructor functions that automatically open the file.
� The constructor functions have the same parameters and defaults as the open()
function. Therefore, you will most commonly see a file opened as shown here:
ifstream mystrearn( myfile ) // open file for input
� As stated, if for some reason the file cannot be opened, the value of the associated
stream variable will evaluate to false.
� Therefore, whether you use a constructor function to open the file or an explicit call to
open( ), you will want to confirm that the file has actually been opened by testing the
value of the stream.
� You can also check to see if you have successfully opened a file by using the is_open(
) function, which is a member of fstream, ifstream, and ofstream. It has this prototype:
bool is_opens;
� It returns true if the stream is linked to an open file and false otherwise. For example,
the following checks if my stream is currently open:
� To close a file, use the member function closeO. For example, to close the file linked to
a stream called mystream, use this statement:
mystream close();
� The close() function takes no parameters and returns no value. Writing a Character:
� The C I/O system defines two equivalent functions that output a character: putc() and
fputcO. (Actually, putc() is usually implemented as a macro.) .
� The putc( ) function writes characters to a file that was previously opened for writing
using the fopen() function. The prototype of this function is
int putc(int ch, FILE *fr);
where fr is the file pointer returned by fopen() and ch is the character to be output. The file
pointer tells putc( ) which file to write to.If a putc( ) operation is successful, it returns the
character written. Otherwise, it returns EOF.
Reading a Character:
� There are also two equivalent functions that input a character: getc() and fgetc( ).
� Both are defined to preserve compatibility with older versions of C. The getc( )
function reads characters from a file opened in read mode by fopenO.
� The prototype of getc() is
in getc(FILE *fr);
where fr is a file pointer returned by fopen( ). The getc( ) function returns an EOF when the
end of the file has been reached. Therefore, to read to the end of a text file, you could use the
following code:
do
ch = getc(fp);
while(ch=EOF);
� However, getc() also returns EOF if an error occurs.
� You can use ferror() to determine precisely what has occurred.
Reading and Writing Text Files:
� It is very easy to read from or write to a text file.
� Simply use the << and >> operators the same way you do when performing console
I/O, except that instead of using cin and cout, substitute a stream that is linked to a file.
� For example, this program creates a short inventory file that contains each item’s
name and its cost:
#include <iostream>
#include <fstrearm> using narnespace std;
int main()
ofstream out(“inventory”) ; // output, normal file
if(out)
cout << “Cannot open inventory file.\n”;
return 1;
out << “Radios “F << 39,95 << endl; out << “toasters “ << 19.95 << endl;
out << “Mixers” << 24.80 << endl;
out.close()
return 0;
� The following program reads the inventory file created by the previous
program and displays its contents on the screen:
#include <iostream>
#include <fstream> using narnespace std;
int main()
ifstream in(”inventory”); // input
if(in)
cout << “Cannot open inventory file.\n”;
return 1;
}
char item[20];
float cost;
in>>item>>cost;
cout<<item<<cost;
in>>item>>cost;
cout<<item<<cost;
in>>item>>cost;
cout<<item<<cost;
in.close();
return 0;
} Random Access:
� In C++’s I/O system, you perform random access by using the seekg()
and seekp() functions. Their most common forms are
istream &seekg(off_type offset, seekdir origin);
ostream &seekp(off_type offset, seekdir origin);
� Here, off_type is an integer type defined by ios that is capable of
containing the largest valid value that offset can have.
� seekdir is an enumeration defined by ios that determines how the seek
will take place.
� The C++ I/O system manages two pointers associated with a file.
� One is the get pointer, which specifies where in the file the next input
operation will occur.
� The other is the put 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. However, using the
seekg() and seekp() functions allows you to access the file in a
nonsequential fashion.
� The seekg( ) function moves the associated file’s current get pointer
offset number of characters from the specified origin, which must be one
of these three values:
ios::beg Beginning-of-file
ios::cur Current location
ios::end End-of-file
� The seekp() function moves the associated file’s current put pointer offset number of
characters from the specified origin, which must be one of the values just
shown.Generally, random-access I/O should be performed only on those files opened
for binary operations.
� The character translations that may occur on text files could cause a position request to
be out of sync with the actual contents of the file.
Obtaining the Current File Position:
� You can determine the current position of each file pointer by using these functions:
pos_type tellg
pos_type tellp
� Here, pos_type is a type defined by ios that is capable of holding the largest value that
either function can return.
� You can use the values returned by tellg() and tellp( ) as arguments to the following
forms of seekg() and seekp( ), respectively.
istream &seekg(pos_type pos);
ostream &seekp(pos_type pos);
� These functions allow you to save the current file location, perform other file
operations, and then reset the file location to its previously saved location.
I/O Status:
� The C++ I/O system maintains status information about the outcome of each I/O
operation.
� The current state of the I/O system is held in an object of type iostate, which is an
enumeration defined by ios that includes the following members.
Name Meaning
ios::goodbit No error bits set
ios::eofbit 1 when end-of-file is encountered; 0 otherwise
ios::failbit 1 when a nonfatal I/O error has occurred; 0
otherwise
ios::badbit 1 when a fatal I/O error has occurred; 0 otherwise
Namespaces:
� The purpose of namespace is to localize the names of identifiers to avoid name
collisions.
� The C++ programming environment has seen an explosion of variable, function, and
class names.
� Prior to the invention of namespaces, all of these names competed for slots in the global
namespace and many conflicts arose.
� For example, if your program defined a function called abs( ), it could (depending upon
its parameter list) override the standard library function abs() because both names
would be stored in the global namespace.
Namespace Fundamentals:
� The namespace keyword allows you to partition the global namespace by creating a
declarative region.
� In essence, a namespace defines a scope.
� Anything defined within a namespace statement is within the scope of that namespace.
� Namespaces allow to group entities like classes, objects and functions under a name.
This way the global scope can be divided in "sub-scopes", each one with its own name.
� A namespace declaration identifies and assigns a unique name to a user-declared
namespaces.
The format of namespaces is:
namespace identifier
{
entities
}
� Where identifier is any valid identifier and entities is the set of classes, objects and
functions that are included within the namespace.
� For example:
namespace myNamespace
{
int a, b;
}
� In this case, the variables a and b are normal variables declared within a namespace
called myNamespace.
� In order to access these variables from outside the myNamespace namespace we have
to use the scope operator ::.
� For example, to access the previous variables from outside myNamespace we can write:
myNamespace::a
myNamespace::b
� The functionality of namespaces is especially useful in the case that there is a
possibility that a global object or function uses the same identifier as another one,
causing redefinition errors.
� For example:
// namespaces
#include <iostream>
using namespace std;
namespace first
{
int var = 5;
}
namespace second
{
double var = 3.1416;
}
int main () {
cout << first::var << endl;
cout << second::var << endl;
return 0;
} Output: 5
3.1416
� In this case, there are two global variables with the same name: var.
� One is defined within the namespace first and the other one in second.
� No redefinition errors happen thanks to namespaces.
using:
� The keyword using is used to introduce a name from a namespace into the current
declarative region.
� For example:
// using
#include <iostream>
using namespace std;
namespace first
{
int x = 5;
int y = 10;
}
namespace second
{
double x = 3.1416;
double y = 2.7183;
}
int main () {
using first::x;
using second::y;
cout << x << endl;
cout << y << endl;
cout << first::y << endl;
cout << second::x << endl;
return 0;
} Output: 5
2.7183
10
3.1416
� Notice how in this code, x (without any name qualifier) refers to first::x whereas y refers to second::y, exactly as our using declarations have specified.
� We still have access to first::y and second::x using their fully qualified names.
• The keyword using can also be used as a directive to introduce an entire
namespace:
// using
#include <iostream>
using namespace std;
namespace first
{
int x = 5;
int y = 10;
}
namespace second
{
double x = 3.1416;
double y = 2.7183;
}
int main ()
{
using namespace first;
cout << x << endl;
cout << y << endl;
cout << second::x << endl;
cout << second::y << endl;
return 0;
} Output: 5
10
3.1416
2.7183
� In this case, since we have declared that we were using namespace first, all direct uses of x and y without name qualifiers were referring to their declarations in namespace first.
• using and using namespace have validity only in the same block in which they are
stated or in the entire code if they are used directly in the global scope.
• For example, if we had the intention to first use the objects of one namespace and then
those of another one, we could do something like:
// using namespace example
#include <iostream>
using namespace std;
namespace first
{
int x = 5;
}
namespace second
{
double x = 3.1416;
}
int main () {
{
using namespace first;
cout << x << endl;
}
{
using namespace second;
cout << x << endl;
}
return 0;
} Output: 5
3.1416 The STD Namespace:
� Standard C++ defines its entire library in its own namespace called std.
using narnespace std
� This causes the std namespace to be brought into the current namespace, which gives
you direct access to the names of the functions and classes defined within the library
without having to qualify each one with std::.Of course, you can explicitly qualify each
name with std:: if you like.
� For example, the following program does not bring the library into the global
namespace.
#include <iostream>
int main()
int val;
std: :cout << “Enter a number: “;
std: :cin >> val;
std: :cout << “Ihis is your number:”;
std::cout << std::hex << val;
return 0;
� Here, cout, cin, and the manipulator hex are explicitly qualified by their namespace.
� That is, to write to standard output, you must specify std::cout; to read from standard
input, you must use std::cin; and the hex manipulator must be referred to as std::hex.
� You may not want to bring the standard C++ library into the global namespace if your
program will be making only limited use of it.
� However, if your program contains hundreds of references to library names, then
including std in the current namespace is far easier than qualifying each name
individually.
ANSI String Objects: � The strings are implemented in C as character arrays. However, character arrays have a
few limitations when treated as strings.
• They cannot be compared like other variables.
• They cannot be assigned like normal variables.
• Initializing with another string is not directly possible.
• There are functions provided for strings in the library, prototypes of which are
accessible using string.h file. These functions are not string function in true
sense. They operate on character pointers.
� Therefore, it is desirable that to treat strings as separate objects and as
character arrays. C++ overcomes these limitations by providing string
objects.
� C++ does not support a built-in string type . It does, however, provide
for two ways of handling strings.
� Null-terminated character array sometimes referred to as a C string. The
second way is as a class object of type string.
� Actually, the string class is a specialization of a more general template
class called basic_string.
� In fact, there are two specializations of basic_string: string, which
supports 8-bit character strings, and wstring, which supports wide-
character strings. Since 8-bit characters are by far the most commonly
used in normal programming, string is the version of basic_string
examined here.
� Given that C++ already contains some support for strings as null-
terminated character arrays, it may at first seem that the inclusion of the
string class is an exception to this rule.
� However, this is actually far from the truth. Here is why: Null-
terminated strings cannot be manipulated by any of the standard C++
operators. Nor can they take part in normal C++ expressions.
Operations on Strings:
1. Creation of strings:
A String object can be created in the following three ways:
a. Defining a string object in a normal way:
� We can write
string StingName;
to define the string object in a normal way.
b. Defining a string object using initialization:
� We can write
string AStringObject(AnotherString Object) or
AStringObject = AnotherStirngObject
to define and initialize AStringObject using AnotherStirngObject.
c. Defining a string object using a constructor:
We can write
string AStringObject(value) or
string AStringObject = Value
to use a single argument constructor to define AStringObject and initialize it with value.
Example:
// DefineStrings.cpp
#include<iostream.h>
#include<string.h>
using namespace std;
int main()
{
string FirstString; // Normal definition
string SecondString(“Hi”); //Definition using one argument constructor
string ThirdString(SecondString); //Definition using initialization
FirstString = ” Hoe are you”; /* Using a conversion function from normal strng to the
string object. This conversion function is an outcome of a non-explicit one argument
constructor */
string ForthString = FirstString; //defining and initializing
}
2. Substring Operations:
There are a few substring operations as well.
a). Find location of a substring or a character in a given string:
� There is a function find() which finds the specific substring or character in a given
substring.
� Find returns the location or position at which that character of that string resides in the
given string.
� The first position is numbered as zero and second is numbered as 1 like C strings.
b) Find the character at a Given Location in a given string:
� There is a function at() which tells us which character lies at a given position.
� If we define string FirstString(“This is testing”); FirstString.at(1) returns h because h is
a character at 1st position.(remember the string starts from 0th position).
c) Insert a specific Substring at a Specific Place:
� We can insert a specific substring in a given place in the string using function
insert(PositionAtWhichInsertionToBeMade, StringToBeInserted).
� The following example will show how a substring “busy” is inserted at position number
4 in the string “How Are You” to make it “How busy Are You”.
d) Replacing Specific Character by Other Characters:
� We can replace specific sequence of characters (a substring) by another sequence of
characters(i.e., another substring) in a given string.
� Our example shows how busy is replaced by lazy.
� Through our example, uses same number of characters in the replacement string, it is
not necessary. We can even replace “busy” with “busy and tired”.
e) Append Substring to a String.
� The append function is available to add a substring at the end of a given string. Append
is called with just one argument; the substring to append. The following program has
one such use of append. It appends “friend” to the SecondString variable to make it “Hi
friend!”.
3. Operations involving Multiple Strings:
(i) + = and compare function (ii) Swapping two strings. 4. Finding characteristics of a string.