310 likes | 327 Views
File I/O. ifstreams and ofstreams Sections 11.1 & 11.2. 1. Introduction. Up to now we have been: getting input from the keyboard via cin sending output to the screen via cout and cerr We now see how to: get input from a text file send output to a text file. 2. data1.txt.
E N D
File I/O ifstreams and ofstreams Sections 11.1 & 11.2 1
Introduction • Up to now we have been: • getting input from the keyboard via cin • sending output to the screen via coutand cerr • We now see how to: • get input from a text file • send output to a text file 2
data1.txt 8097 93.57265.8 . . . 68.3 Problem Using OCD, design and implement a program that computes the average of a sequence of numbers stored in a file. Project 9 3
data1.txt 8097 93.57265.8 . . . 68.3 Preliminary Analysis • Using #include <iostream>, a program can read from the keyboard via the istream named cin, • but this is of little benefit when the data we need is in a file. • What we need is a way to somehow establish an _________-like connection between our __________ and the_________________, such that we can then read from the file via that connection. Program 4
Behavior • Our program should display its purpose and then display a prompt for the name of the input file, which it should then read. • Our program should open a connection from itself to that input file. It should • then read the numbers from the input file via the connection, and compute their sum and count. It should then • close the connection, and compute and display the average of the numbers. Program data1.txt 8097 93.57265.8 . . . 68.3 5
Objects • Description Type Kind Name purpose, prompt string constant (none) file name string varying inFileName connection ?? varying fin a number double varying number sum double varying sum count double varying count average double varying average 6
Operations or >> if no blanks in filenames • Description Library? Name display a string string << read a string string getline() open a connection ????to a file read numbers via ????connection sum & count numbers built-in +=, ++, loop close connection ???? compute average built-in / display average iostream << 7
Algorithm • 0. Display purpose of program, and prompt for input file name. • 1. Read name of input file from cin into inFileName. • 2. Open connection named fin to file named in inFileName. • 3. Initialize sum, count to zero. • 4. Loop: • a. Try to read a value from fin into number; • b. If no values were left, terminate repetition. • c. Add number to sum. • d. Increment count. • End loop. • 5. Close fin. • 6. If count > 0 • a. Compute average = sum / count. b. Display count and average with appropriate labels • Else • display error message. 8
Implementation in C++ • To establish connections to an file, the ___________ library provides file-stream types : • the ifstreamclass for input streams • the ofstreamclass for output streams • The programmer uses these types to declare file-stream objects; for example, • _______________________ • _______________________ 9
To connect such fstream objects to files: • Method 1: Use the open() function member in these classes: • ifstream fin; • __________________________________; • ofstream fout; • __________________________________; • Method 2: Use initializing declarations: • ifstream fin("name of file"); ofstream fout("name of file"); 10
Disadvantage of "hard-wiring" actual file) into a program: the program must be modified when using a different file. • A better alternative: Have user enter the file name and store it in a string variable; for example, • string inFileName; cout << "Enter name of file: "; getline(cin, inFileName); • When attaching an fstream to this file, we must use string's _____________ (or c_str()) function member to extract the actual file name stored in the string object; for example, • ifstream _____________________________; • Similar declarations are used for output streams. or use >> ifno blanks in filenames 11
How to read from / write to a file connected to an fstream: • Input: Use ____just like from an____________; • fin >> var; • Output: Use ____just like from an____________; • fout << expr; or getline() Note: For output, we can use any of the format manipulators such as endl, fixed, setprecison(), and setw() ifstream inherits everything from istream ofstream " " " ostream 12
When we are finished with a file — both for input and output files — we should break the connection between it and the program. Although this will happen automatically when the connection reaches the end of its scope, it is a good idea to do this explicitly with the fstream's function member ____________; for example, fin.close(); fout.close(); 13
Objects • Description Type Kind Name purpose, prompt string constant (none) file name string varying inFileName connection ifstream varying fin a number double varying number sum double varying sum count double varying count average double varying average 14
Operations • Description Library Name display a string string << read a string string getline() open a connection fstream declarationto a file of fstream (or open()) read numbers via fstream >>connection sum & count numbers built-in +=, ++, loop close connection fstream close() compute average built-in / display average iostream << or >> 15
In Visual C++:create it in Visual C++ and "Add to" project. Must be in same folder as program.cppand the .vcproj • Two More Problems: • Opening a file for input can fail. • Solution: Use the ifstream function member _______________. • ifstream fin(infileName.data()); assert(_______________________); 2. How do we know when we all the data in the file has been read? The ifstream function member _________ returns true if an _________________ readfound no data remaining in the file. Must tryto read and fail 16
Note Coding • /*------------------------------------------------------------- • Program to read data values from a text file, count them, • and find their average. • Input(keyboard): Name of the file • Input(file): doubles • Output(screen): Prompts, average of the data value with labels, or file-empty message • -------------------------------------------------------------*/#include <iostream> // cin, cout, ... • ______________________________ // ifstream, ofstream, ... • #include <string> // string#include <cassert> // assert()using namespace std;int main(){ cout << "\nTo average the numbers in an input file," << "\nenter the name of the file: "; • string inFileName; • getline(cin, inFileName; 17
OR: ifstream fin; fin.open( infileName.data() ); • ________________________________; // open the connection ________________________________; // verify it opened double number, sum = 0.0; // variables for int count = 0; // computing average for (;;) // input loop { _____________________; // read number if (_______________) break; // if none were left, quit sum += number; // add it to sum count++; // bump up count } // end loop _______________________; // close fstream 18
if (count > 0) { double average = sum / count; cout << "\nThe average of the values in " << inFileName << " is " << average << endl; } else cout << "\n*** No values found in file " << inFileName << endl; } 19
Testing • To test our program, we use a text editor and create some easy-to-check input files such as 10 20 30 40 • If we name this particular file test1.txt and enter its name when prompted by our program, the average value produced should be 25. Create text files in Visual C++ 20
To average the numbers in an input file, enter the name of the file: test1.txt The average of the values in test1.txt is 25 • Continue testing using other input files, trying to find places where our program breaks down. • And it is is important to try various kinds of files — ascending order, descending order, random order, files with 1 element, empty files . . . — because programs that work for some of these may fail for others. E.G., Project 9 21
data1.txt 8097 93.57265.8 . . . 68.3 • Once we are confident that our program is correct, we can execute it with the data file from our problem: To average the numbers in an input file, enter the name of the file: data1.txt The average of the values in test1.txt is 80.1 22
Key Things to Remember • The fstream library defines two classes: • ifstream, for creating connections between programs and input files; and • ofstream, for creating connections between programs and output files. • Both ifstream and ofstream objects are createdin a similar fashion. 23
If inFileName contains the name of an input file, and outFileName contains the name of an output file, then the statements ifstream fin(inFileName.data()); ofstream fout(outFileName.data()); define fin and fout as connections to them. • Note that the string function member data() (orc_str()) must be used to retrieve the actual char-acters of the file’s name from the file stream object. or: ifstream fin; fin.open(inFileName.data()); or: ofstream fout; fout.open(outFileName.data()); 24
If a program tries to open an ifstream to a file that doesn’t exist, the open is said to fail. • To check whether or not an ifstream is open, the ifstream class provides the is_open()function member, which returns true if the ifstream was successfully opened, and false if it not. • Whether or not a file opened correctly should always be verified using is_open(). assert(fin.is_open());or assert(!fin.fail()); or use an if 25
Important Notes About Output Files: • If a program tries to open an ofstream to a file that doesn’t exist or that can't be found, the open operation creates a new __________________ for output. • If a program tries to open an ofstream to a file that does exist, the open operation (by default) ____________ that fileof its contents, creating a clean file for output. _____________it!Be careful! To open an existing file for output without emptying it, the valueios::appcan be given as a second argument: ofstream fout(outFileName.data(), ios::app); Output will be appended to whatever is already in the file. 26
For rare occasions where a file is needed for both input and output, the fstream class is provided: • fstream fInOut(ioFileName.data(), • ios::in | ios::out); • This statement defines an fstream named fInOut to a file, from which data can be read, and to which data can be written. • The bitwise OR operator (|) is used to combine file open-modes in this manner. 27
Summary • #include <fstream> to use file streams. • To establish a connection to a file whose name is given by a string variable fileName: • For input: ifstream fin(fileName.data()); • or: ifstream fin; fin.open(fileName.data()) • For output: ofstream fout(fileName.data()); • or: ofstream fout; fout.open(fileName.data()) Note: data() (orc_str()) must be used to retrieve the actual characters of the file’s name from fileName. 28
To check whether or not an ifstream is open: assert(fin.is_open());or assert(!fin.fail()); (or use an if statement) • Once an ifstream (or ofstream) has been opened, it can be read from (or written to) using the usual input (or output) operations: • input: >>, get(), getline(), ... • output: <<, put(), ... • In general,anything that can be done to an istream (or ostream) can be done to an ifstream (or ofstream). 29
The eof() function member provides a convenient way to build input loops: for (;;) { fin >> someValue; if (fin.eof()) break; // ... process someValue } • Remember that opening a file for output erases any contents in the file. 30
Once we are done using an ifstream (or ofstream), it should be closed using the close() function member: fin.close(); fout.close(); Most systems limit the number of files a program can have open simultaneously, so it is a good practice to close a stream when finished with it. • A closed file can be (re)opened using open(): fin.open(inFileName.data()); fout.open(outFileName.data()); 31