C++: Notes: File I/O #1
File I/O Notes #1:
Basics of Reading from a File
Streams
Up until this point all of your programs have used what’s called the “Standard I/O Stream.” You’ve included the library iostream in all your code so you could access input data from the keyboard and send output to the monitor. The cin keyword accesses the standard input stream (the keyboard).
You can think of the keyboard placing pieces of data into a stream (like a small river) that flows past your program in the computer. When you use cin, your program draws some of that data out of the stream and into the program to use.
Figure 1. cin is used to take data from the standard input stream (the keyboard)
It is possible to access different input streams. That is what we will do when we use external files. We can read data into our programs from an external file (such as one we create in notepad) at points in our program when we want input to come from a file instead of the keyboard.
Figure 2. ifstream type stream objects are used to take data from a stream coming from an external file
Library
The first step in working with external files is to include the fstream library (f is short for file). Note: you will probably still want to include iostream as well, because you may still need some pieces of input from the keyboard and you’ll probably want to send information to the monitor.
#include<fstream>
Creating an ifstream Object
The second step is to create an object of type ifstream (in – file – stream). The fstream library provides a definition for a class called ifstream. You will instantiate an object of this class so you can associate it with a particular external file in memory. This can go along with your other variable declarations in main. There are two techniques for constructing an ifstream object:
Technique #1
ifstream infile("h:\\ask-not.txt"); //makes an object of type in-file stream
Technique #2
ifstream infile2;//can make one
infile2.open("h:\\ask-not.txt");//and then open file
Some important things to remember about opening a file to read data into your program:
- The file must already exist
- It’s a good idea to put the word in and file somewhere in the name of the identifier so you (and others reading your code) can tell what the object is being used for really easily.
- You will need to specify the entire file path…ex…H:\\My Documents\\myFile.txt (note that since we are putting the file name in a string, we would need to use 2 backslashes in order to specify one backslash in the file path due to escape sequences.
Checking if File Opening was Successful
Before you make any attempts to read from a file, you need to make sure it successfully opened. You can do this using a method of the ifstream class called fail that returns a Boolean true if the last attempted operation on the file failed.
Example:
#include<iostream>
#include<fstream>
usingnamespace std;
int main()
{
ifstream infile("h:\\myFile.txt");
if(infile.fail())
{
cout<"Problem opening file.";
}
else
{
//...do whatever based on successfully opening the file
Reading in Data
To read in data, you will use the name of your ifstream object just as if it were the cin keyword.
When I want to read a single value from the keyboard’s stream, where that value is delimited (marked) by the first whitespace character I encounter, I would do something like the following:
string s;
cin>s;
We can use our ifstream object in basically the same way:
string s;
infile>s;
//assumes that we alredy constructed infile and successfully opened the file
We will read up to the first whitespace into the string object called s.
Important:
Note – just like when using cin, if I am expecting the value being read to be numeric (i.e. I am reading straight into an int or double variable), then I need to be absolutely sure that the value coming out of the file is going to be numeric, or I am going to end up with similarly disastrous results as when we attempt this with cin.
Reading an Entire Line
If I want to read an entire line of input from the keyboard delimited by a newline (pressing of the enter key), I can do this using the getline function, as shown here:
string s;
getline(cin,s); //gets entire line of text into s variable
I can use the same technique with an ifstream object, again simply using the name of my identifier in place of the cin:
string s;
getline(infile,s);
//assumes that we alredy constructed infile and successfully opened the file
Figuring Out When We’re Finished
Using the Result of the Read
You can use the read itself as the condition for the loop, as in the following two examples:
Example 1:
while(infile>s)
{
cout<s<endl;
}
Example 2:
while(getline(infile,s))
{
cout<s<endl;
}
Closing the File
When we’re finished we generally want to close our file. This is particularly important if we want to reuse the same ifstream object during the program to open another file. (Note: we can have multiple files open by using multiple ifstream objects if desired). Closing is easy:
infile.close();
Clearing the File
If you intend to reuse the filestream in your program (say you open one file at the beginning, close it, and then want to reuse your variable to open another filestream later), then you need to flush it out with the clear method. This is also easy:
infile.clear();
Full Program Example
#include<iostream>
#include<fstream>
#include<string>
#include<conio.h>
usingnamespace std;
int main()
{
ifstream infile("h:\\myInputFile.txt"); //open my file (created in Notepad)
string s; //string variable to hold file input
int n; //int variable to hold a number from file input
if(infile.fail()) //ensure file opening was successful
{
cout<"Problem opening file."; //error msg if file failed
}
else
{
while(getline(infile,s)) //read lines while still more to get
{
cout<s<endl; //output results to screen as we go
infile>n; //read the integer
cout<n<endl;
infile.ignore(); //need to take care of usual problem switching between reads
}
}
infile.close(); //close the file
_getch();
return 0;
}