Reading and writing to a file involves using streams.
A stream is essentially a channel in which data flows from the source to a
destination.
Input streams direct data from a source, such as the keyboard or a file
into variables of a program, and output streams send data out.
As you may have realized by now, the standard input stream cin
is an input stream from the keyboard and the standard output stream
cout sends data to the screen.
Input and output streams such as "cin" and "cout"
are examples of stream objects.
Learning about streams now as objects is a good way to introduce some of
the syntax and ideas behind the object-oriented aspect of C++.
To use file input and output streams, we will need to include a C++ header
file called <fstream> that contains the necessary operations
to perform these functions.
Programs that read and write to disk must therefore have the following
include directive at the top:
#include <fstream> |
ifstream in-name" for
input and "ofstream out-name" for output streams.
For example, the following statements inform the compiler to create a stream
called in_stream that is an input-file-stream object and another
called out_stream that is an output-file-stream object:
ifstream in_stream; ofstream out_stream; |
| WARNING: |
This analogy works up to a point.
For example, you cannot use assignments with class objects, so the following
code fragment will not work:
|
|---|
setf and
precision for formatting our output streams using cout.
These functions are defined in more detail on pages 219-220 in the text, but
they are included briefly for cout:
// Use cout's member function "set flags" function, called setf // The argument here means to use fixed point rather than scientific notation cout.setf(ios::fixed); // Use cout's setf function again, but this time, the argument tells cout to // show the decimal point. cout.setf(ios::showpoint); // Use cout's member function, called precision // The argument indicates to display 2 digits of precision after the decimal point cout.precision(2); |
| NOTE: | A flag in objects is simply a property that has only 2 options.
In this case, either cout will display a double in fixed point or
in scientific notation.
Similarly, either it outputs a number with the decimal point or not.
|
|---|
open(filename).
For example, the following statement will 1) open a file called "myFile",
assuming one with that exists in the current directory (more on this later),
and 2) connect in_stream to the beginning of the file:
in_stream.open("myFile");
|
The ofstream class also has an open(...)
member function, but it is defined differently.
Consider the following statement:
out_stream.open("myFile");
|
ofstream object, the function also either:
To disconnect the ifstream in_stream to whatever file it opened,
we use its close() member function:
|
close() function, which also adds an end-of-file marker
to indicate where the end of the file is:
out_stream.close(); |
fail():
in_stream.fail(); |
#include <iostream> // for cout definition
#include <fstream> // for file I/O definitions
#include <cstdlib> // for the fail member function
using namespace std;
int main() {
ifstream in_stream;
in_stream.open("myFile");
if( in_stream.fail() ) {
cout << "Sorry, the file couldn't be opened!\n";
exit(1);
}
// the rest of the main function using in_stream defined here...
} // end of the main function
|
if conditional checks to see if
there was an error.
If so, the program will output the apologetic error message and then exits.
The exit(1) function from the library "cstdlib" enables the program
to terminate at that point and have it return a "1" versus a "0".
cin and
cout, the operators ">>" and
"<<" perform the same direction of data for files, with
the exact same syntax.
For example, execution of the following statement will write the number 25, a space, the number 15 and another space into the file opened by out_stream:
out_stream << 25 << ' '; out_stream << 15 << ' '; |
in_stream >> inputn; |
eof()
Many development environments have I/O libraries that define how the
member function eof() works for ifstream variables
to test if this flag is set to True or False.
Typically, one would like to know when the EOF has not been reached, so
a common way to use this function is as a negative boolean value.
An alternative implementation is to keep reading using the >>
operator, which succeeds when there is still something left to read.
The following two code fragments highlight the possibilities:
Using "eof()"
| Using ">>"
| ||||
|---|---|---|---|---|---|
|
|
make_neat(...) function.
// File Name: Neatify.cpp (Display 05-06.cpp)
// Illustrates output formatting instructions.
// Read all the numbers in the file rawdata.dat and write the numbers
// to the screen and to the file neat.dat in a neatly formatted way.
#include <iostream> // for cout
#include <fstream> // for I/O member functions
#include <cstdlib> // for the exit function
#include <iomanip> // for the setw function
using namespace std;
void make_neat(ifstream& messy_file, ofstream& neat_file,
int number_after_decimalpoint, int field_width);
int main() {
ifstream fin;
ofstream fout;
fin.open("rawdata.txt");
if( fin.fail() ) { // oops the file did not exist for reading?
cout << "Input file opening failed." << endl;
exit(1);
}
fout.open("neat.dat");
if( fout.fail() ) { // oops the output file open failed!
cout << "Output file opening failed.\n";
exit(1);
}
make_neat(fin, fout, 5, 12);
fin.close( );
fout.close( );
cout << "End of program." << endl;
return 0;
}
// Uses iostreams, streams to the screen, and iomanip:
void make_neat(ifstream& messy_file, ofstream& neat_file,
int number_after_decimalpoint, int field_width) {
// set the format for the neater output file.
neat_file.setf(ios::fixed);
neat_file.setf(ios::showpoint);
neat_file.setf(ios::showpos);
neat_file.precision(number_after_decimalpoint);
// set the format for the output to the screen too.
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.setf(ios::showpos);
cout.precision(number_after_decimalpoint);
double next;
while( messy_file >> next ) { // while there is still stuff to read
cout << setw(field_width) << next << endl;
neat_file << setw(field_width) << next << endl;
}
}
|
char data type that allows
users to store manipulate a single character at a time.
A sequence of characters such as "myFileName.dat" can be stored in a
C-string, which is declared as follows:
char C-string_name[LEN]; |
LEN - 1 characters.
The square brackets after the variable name indicate to the compiler the maximum
number of character storage is needed for the variable.
| Warning: | This number must be one greater than the number of actual characters! |
|---|
C-strings are an older type of string that was inherited from the C language, and people frequently refer to both types as "strings", which can be confusing.
// File Name: Streams.cpp
// Ask the names for the input and output files.
// Reads three numbers from the input file, sums the numbers, and writes the
// sum to both the screen and the output file specified by the user.
#include <fstream>
#include <iostream>
#include <cstdlib>
int main() {
using namespace std;
char in_file_name[16], out_file_name[16]; // the filenames can have at most 15 chars
ifstream in_stream;
ofstream out_stream;
cout << "This program will sum three numbers taken from an input\n"
<< "file and write the sum to an output file." << endl;
cout << "Enter the input file name (maximum of 15 characters):\n";
cin >> in_file_name;
cout << "\nEnter the output file name (maximum of 15 characters):\n";
cin >> out_file_name;
cout << endl;
// Condensed input and output file opening and checking.
in_stream.open(in_file_name);
out_stream.open(out_file_name);
if( in_stream.fail() || out_stream.fail() ) {
cout << "Input or output file opening failed.\n";
exit(1);
}
double firstn, secondn, thirdn, sum = 0.0;
cout << "Reading numbers from the file " << in_file_name << endl;
in_stream >> firstn >> secondn >> thirdn;
sum = firstn + secondn + thirdn;
/* The following set of lines will write to the screen */
cout << "The sum of the first 3 numbers from " << in_file_name
<< " is " << sum << endl;
cout << "Placing the sum into the file " << out_file_name << endl;
/* The following set of lines will write to the output file */
out_stream << "The sum of the first 3 numbers from " <<
in_file_name << " is " << sum << endl;
in_stream.close( );
out_stream.close( );
cout << "End of Program." << endl;
return 0;
}
|
double separated by blanks and/or
line breaks, and there is at least one real number (i.e. it is not empty).
// Course: CSC 306 Introduction to Programming with C++
// Name: Your Name
// Assignment #10: <Put a brief sentence about your program here.>
/*
Purpose: <Put a more in-depth description of the program here.>
*/
This assignment must be completed individually.
When you are finished with your assignment, drop your source code into the CSC306_A10 dropbox on the Academic server.