Hello again! In this video, we are going to look at files and streams. You probably have some idea of
what a file means.
C++ has a very minimalistic interpretation.
A file is just a sequence of bytes, which has some file name to identify it.
So we do nt need to know whether the data is stored on a disk or an SD card or some physical device
that is pretending to be a file.
We do not know how exactly it is stored, and we do not care what it is meant to represent.
The C++ library provides fstream objects for interacting with files.
These are very similar to the iostream objects that we have used for interacting with the console, to send
output to the console and read input from it.
These fstream objects always access files sequentially, so that means one byte after another.
You cannot jump forwards or go backwards, and they are always in the same order.
The stream does not know how much data it is going to send or receive, and the stream has no concept of
structure to the data.
So this means, in particular, that fstreams do not understand file formats.
There are four main things you can do with an fstream object.
You can open it.
So this will start interacting with a file.
This will connect to the string object to the file, if you like.
So after that, the file is available for use by your program.
You can read.
So this means that data is copied from the file into your program's memory.
You can
write,
so that means that data is copied from your programs's memory to the file. And you can close the file.
So after you have finished using your file, you can end your interaction session.
And this will close the connection between the stream object and the file.
And then that file is no longer available for use by the program. Unless an fstream object opens it
again.
Each of these operations is performed by calling a function in the operating system's API. The Application
Program Interface.
So the program is going to stop and wait and then the operating system is going to do the read or whatever.
And then when it finishes, the call to the API will return. And the program will then resume executing
your instructions.
So while this call is being performed, your program has to stop and wait.
It cannot execute any of your code.
We cannot use a file until it has been opened. Once we have finished using a file,
we should close it.
If you are writing to a file, this will make sure that all the data that you wrote is actually saved
correctly.
And also, operating systems have a limit on the amount of files this program can have open at any one
time.
If you try to open too many files, the operating system will stop you.
So this is a bit like allocating memory.
If your program allocates too much memory, the operating system will stop you from allocating more
memory. I actually fell into this once,
many years ago. I had a loop that opened to file, but did not close it.
And then eventually, after 40 iterations or whatever it was, the operating system said,
"Sorry, no more!"
When you compile a C++ program into a binary, the compiler will add some extra runtime code to
the program.
So this will set the program up and then call main().
And then when main() returns, this code will do any clearing up that is needed.
And one of the things it does is that it will go through all the files that the program has opened
and make sure they are closed.
So in theory, you do not actually need to close any files.
But, as with releasing memory, it is a good idea to do it as soon as you can.
It is actually more important with files, because other programs can access files and - well, you can have
file looking, but C++ does not support that directly.
So you could have other programs trying to use your file. So you really want to have your file
open for the shortest possible time.
And then one final point before we go on.
When you send or receive data with a file, it is not going to be actually sent one byte at a time.
The reason is that interacting with physical devices is very time-consuming.
You know, it takes thousands of processor instructions. So you really want to minimize the number
of actual transfers.
So what happens is that the data is gathered up into a memory buffer.
And then when it reaches the optimal size, the data gets sent off to the device.
So this reduces the number of actual transfers, so that reduces the number of times your program has
to stop and wait.
However, there is a disadvantage to this. If your program waits too long between transferring data,
then the discrepancy, between what the file says, and what your program thinks the file says, will get bigger
and bigger.
And that can cause problems.
But we will come back to that.
Okay, so that's it for this video.
I'll see you next time.
But meanwhile, keep coding!