The following member functions are particularly useful for disk input. See the Class Libraries Reference for a complete list of stream member functions.
If you are using an input file stream (ifstream), then you must associate that stream with a specific disk file. You can make this association in the constructor, or you can use the open function. In either case, the parameters are the same.
You generally specify an open_mode when you open the file associated with an input stream (the default mode is ios::in). For a list of the open_mode flags, see the description of the open function in “Output Streams” on page 365. The flags can be combined as appropriate using the bitwise OR (|) operator.
If you want to read an existing file, you must test for the possibility that the file does not exist. For a description of the fail member function, see “Error Processing Functions” on page 377.
istream ifile( "FILENAME", ios::nocreate );
if ( ifile.fail() )
// The file does not exist ...
The unformatted get member function works like the >> operator with two exceptions. First, the get function always includes white-space characters, whereas the extractor excludes white space when the ios::skipws flag is set (the default). Secondly, the get function is less likely to cause a tied output stream (cout, for example) to be flushed.
Example 16
Example 16 illustrates how the behavior of the extraction operator is different than that of the get member function.
// exios116.cpp
// The istream get member function
#include <iostream.h>
void main()
{
char line[100], ch = 0, *cp;
cout << " Type a line terminated by 'x'\n>";
cp = line;
while ( ch != 'x' )
{
cin >> ch;
if( !cin.good() ) break; // Exits on EOF or failure
*cp++ = ch;
}
*cp = '\0';
cout << ' ' << line;
cin.seekg( 0L, ios::end ); // Empties the input stream
cout << "\n Type another one\n>";
cp = line;
ch = 0;
while ( ch != 'x' )
{
cin.get( ch );
if( !cin.good() ) break; // Exits on EOF or failure
*cp++ = ch;
}
*cp = '\0';
cout << ' ' << line;
}
The program reads two strings from the keyboard one character at a time. The first input operation uses the extraction operator, and the second one uses the get member function. If you type Time to exit for both entries, the screen would look like this:
You can see that the extraction operator skips over the white-space characters (because the ios::skipws flag is set by default) and the get function does not. The program needs the x terminator because it needs to know when to stop reading. Because cin is attached to the C run-time library stdin file, the program does not see any characters until you type the carriage return.
Example 17
A variation of the get function allows you to specify a buffer address and the maximum number of characters to read. This is useful for limiting the number of characters sent to a specific variable, as the following example code shows.
// exios117.cpp
// Using get with a buffer and length
#include <iostream.h>
void main()
{
char line[25];
cout << " Type a line terminated by carriage return\n>";
cin.get( line, 25 );
cout << ' ' << line;
}
In this particular example, you can type up to 24 characters (because strings must end with a null). If you type more than 24, the additional characters remain in the stream and are available for later extraction.
The getline function works in almost the same way as the get function. Both functions allow a third argument that specifies the terminating character for input. If you do not include that argument, its default value is the newline character.
The difference between the two is that get leaves the terminating character in the stream and getline removes the terminating character and throws it away. Both functions reserve one character for a terminating null (in C and C++, all strings end with a null).
Example 18
Example 18 uses the getline function with a third argument to specify a terminating character for the input stream:
// exios118.cpp
// The istream getline member function
#include <iostream.h>
void main()
{
char line[100];
cout << " Type a line terminated by 't'" << endl;
cin.getline( line, 100, 't' );
cout << line;
}
If you type I like elephants., the program screen contains these lines:
The program stops after reading the letter t and leaves the remaining characters, starting with s, in the stream. The next extraction operation or call to get will read the letter s.
If you had used the get member function instead of the getline function, the screen display would be the same, but the next character retrieved would be the letter t.
The read member function reads a sequence of bytes from a file to a specified area of memory. The number of bytes read is determined by the specified length parameter. Reading will otherwise stop if the physical end of file is reached or, in the case of a text-mode file, if an embedded EOF character is read.
Example 19
Example 19 shows how to use the read function to read a binary record from a payroll file into a structure:
// exios119.cpp
// The istream read function
#include <fstream.h>
#include <fcntl.h>
#include <io.h>
void main()
{
struct
{
double salary;
char name[23];
} employee;
ifstream is( "payroll", ios::binary | ios::nocreate );
if( is ) { // ios::operator void*()
is.read( (char *) &employee, sizeof( employee ) );
cout << employee.name << ' ' << employee.salary << endl;
}
else {
cout << "ERROR: Cannot open file 'payroll'." << endl;
}
}
This program assumes that the data records are formatted exactly as specified by the structure with no terminating carriage return or linefeed characters. For a description of binary file processing, see “Binary Output Files” on page 378.
An input file stream keeps an internal pointer that corresponds to the position in the file where data will be read next. The seekg member function sets that pointer.
Example 20
Example 20 opens a file, changes the input position, and then reads to end of the file:
// exios120.cpp
// The seekg member function
#include <fstream.h>
void main()
{
char ch;
ifstream tfile( "payroll", ios::binary | ios::nocreate );
if( tfile ) {
tfile.seekg( 8 ); // Seek eight bytes in (past salary)
while ( tfile.good() ) { // EOF or failure stops the reading
tfile.get( ch );
if( !ch ) break; // quit on null
cout << ch;
}
}
else {
cout << "ERROR: Cannot open file 'payroll'." << endl;
}
}
You can use the seekg function to implement record-oriented data management systems. Multiply the fixed-length record size by the record number to obtain the byte position relative to the end of the file, then use the two-argument get function to read the record.
Example 21
The tellg member function returns the current file position for reading, as illustrated by Example 21:
// exios121.cxx
// The tellg function
#include <fstream.h>
void main()
{
char ch;
ifstream tfile( "payroll", ios::binary | ios::nocreate );
if( tfile ) {
while ( tfile.good() ) {
streampos here = tfile.tellg();
tfile.get( ch );
if ( ch == ' ' )
cout << "\nPosition " << here << " is a space";
}
}
else {
cout << "ERROR: Cannot open file 'payroll'." << endl;
}
}
The program reads the file built by an earlier example and displays messages that show the character positions of any spaces it finds. The tellg function returns a value of type streampos, which is a typedef defined in IOSTREAM.H.
Use the close member function to close the disk file associated with an input file stream. The file should be closed to free the operating system file handle. The ifstream destructor closes the file for you (unless you called attach or passed your own file descriptor to the constructor), but you can use the close member function if you need to open another file for the same stream object.