Hello again in this video, we're going look at file streams.
We already know about input-output streams.
cout and cin are objects of the ostream and istream classes.
There is also fstream.
So ofstream is a class for writing to files and ifstream is a class for reading from files.
Unlike consoles, where there is only one console per computer, there can be many files.
So when we use a file stream, we need to say which file we are going to use it with.
The easiest way to do that is to pass the name of the file as the argument to the constructor of the
file stream.
So if we create an ifstream object for reading from a file, and we pass text dot txt as the argument, then
the constructor of the file stream will open that file for reading.
So that's going to set up the communication channel between the file and our program.
The constructor will perform an open operation, which could fail; if the file does not exist or we are
not allowed to read from it.
So we need to check that we have a valid file stream object before we can use it.
We can do that very easily, by putting the name of the object as a conditional. If the file stream is
valid,
this will be true. And then we can use the file stream to reach from the file.
If the file stream is invalid, if the file could not be opened, then this would be false. And then
we can go into an else branch which will handle the error.
Incidentally, the in the version of C++ which introduced the standard string, they forgot to provide
a constructor, which takes a standard string.
But that has now been fixed. So you can now pass a string object as the argument to a file stream
constructor.
Reading from a file is the same as reading from standard input with cin. So we can just use the right
shift operator, the double angle brackets.
So this will cause the stream to fetch one value at a time from the file and put it in this variable.
A value is defined as something that is separated by white space.
So every time the stream encounters a space or tab or new line, it will decide that is the end of a
value. And the next one starts after the end of the white space.
And that can be problematic with keyboards, but more so with files.
Often the space is actually part of the data that you want.
Also, files often have some kind of structure. They have different fields which have a meaning.
And in that case, your code has to match the structure of the file. And getting that right can
be quite difficult.
And also the question of error handling. If the structure of the file does not exactly match what you
expect, perhaps the structure has changed or maybe you made a mistake?
Or the file structure may have been corrupted.
Let's have a look at using the right shift operator to read data from a file. So we are opening our
file, text dot txt for input, to read from it.
We check that the file was opened successfully.
Then we have a string variable, which is going to hold the data from the file and then we read from
it. One word at a time or one data field, if you like.
And when there is no more data, this will return false and the loop terminates.
We just print out each field as we get it, and then we close the file.
So the close member function will cause the associated file to be closed.
In that case, the stream object is no longer bound to the file, and it is just an empty stream object,
which does not represent any file.
So before we actually run this, we need to get a file to read from.
In most IDE's, you can just take a file and drag it into the project directory and drop it.
If you are using a command line,
you could create the file in the directory where the program is going to run. With Visual Studio,
you need to add it to the project, so you do Project, Add New Item.
And then you have to find out where the text file is.
I sometimes wonder if Microsoft has a special department that is responsible for moving things around,
so no-one can find them! In this version of Visual Studio, it is in Utility.
And then there is Text File.
So let's make that lowercase, so it matches the slide.
And then we can paste some data into that.
There we go.
If we look at the Solution Explorer,
then we see that we now have this text.txt as part of the project.
So this will actually be in the same directory that the program runs in.
And now we can run it.
So there we are. It has fetched the data from the file, one word at a time, and it has printed them out
with commas between them.
So as we said, there can be some issues with using the right shift operator.
The best way to read input is to use the getline function.
So this will take the stream to read from as the first argument, and a string object as the second
argument.
And then it will read a line, from the file, into this string object.
If there is a new line character, it will regard
that as the end of the line. So it will stop. And it will actually remove that newline character from the
data.
So this string object will contain the entire line of the text, except for the new line character.
getline will return true when it reads a line of text. It will return false when it gets to the end
of the file. So you can put this inside a loop and it will keep looping as long as it reads text,
and then you can process the text inside the loop body. When it gets to the end of the file,
the loop will terminate.
So the advantage of this is that you have the data in a string object and then you can process it as
you want.
So here is the same file again. But this time we are going to use getline to get the data from it.
So there we are.
It has read it in as a single line of text.
So this time there is no commas between the different words.
If we want to write to a file then we use a ofstream. Again, we give the name of the file that we
want to use as the argument to the constructor.
So this will open the communication channel between the program and the file. And this time it is going
to send data from the program to the file.
Again, we need to check the state of the stream.
We need to check that the stream could successfully open the file. And then, to use the stream, we just
use the left shift operator to send data to it.
So, for example, we could create a vector of strings.
We have a range for loop, which iterates over the vector.
So each time through the loop, this will be the next string from the vector.
And then this will cause that string to be sent to the file.
So here is that text. The solution Explorer is covering the attribute, actually, but I am sure you can work
out what should be in there!
So we need to include the fstream header to get the file streams, and then string for the string object
and vector for the vector.
So if we run this program - and by the way, make sure that this file does not have any data that you
want to keep. When we open a file for writing, that will overwrite any data that is already in the file.
So if we run that, then - nothing appears to have happened! But it has actually generated the file.
This file will be in the same directory, the same folder as the one that the program ran in.
So in [Visual Studio], we can do Projects,
Add Existing Item, and then we see that there is the file that we just created. In the directory where
the program read. And then that has now been added to the project.
So it is part of the solution. And then we can just look at that file. And we have "The", comma "quick", comma
"brown."
So each of the elements of this vector has been sent to the file, followed by a comma.
And finally, the destructor of the file stream class. When the destructor is called, the file is automatically
closed.
So this will happen just before the actual stream object is destroyed.
If this is an output stream, then this will make sure that any data that is hanging around in memory
buffers will get written to the file.
So this means that if we have a file stream object, we do not actually need to call close.
We can just leave it and let it go out of scope and it will automatically be handled.
However, it is a good idea to explicitly put in a call to close, as that will make it clear that
we have actually finished with using that particular file.
Okay, so that's it's for this video.
I'll see you next time, but meanwhile, keep coding!