Hello again! In this video, we are going to look at file modes.
When we open a file in C++, there are a number of options we can use.
These options are known as "file modes".
These are basically the same as they are in Unix.
So if you knew about file modes in Unix, you probably know all this!
To use a file mode, we pass it as an optional second argument when we open the file.
So that is when we call the constructor for stream or the open member function.
There are two defaults, which are to use text mode and truncate mode. Text mode means that the
characters are stored in the file as ASCII.
So for example, if we write 42 to a file, the file will store that as the ASCII code for the character
four and the character two.
So those will be the corresponding binary numbers, which I think are 100 and 98.
But don't quote me on that!
Truncate mode means that all the data that is in the file is overwritten, so that is for output files
only. Obviously input files will not be truncated.
So when we open a file, it is opened in truncate mode by default.
All the data is erased. And when we write to the file, that will start writing at the beginning of the
file.
There is also an append mode. So this will preserve the data that is in the file.
And when we write data to the file, this will appear at the end of the file. So it will go after the
data that was already in the file.
To do this, we pass fstream double colon app as the second argument to open.
This is a bitmask.
It is a member of fstream.
Well, actually, it is a member of ios, but you can use fstream or ios here.
So this will open the file in append mode, the data in the file will be preserved and the
write operation will add data at the end of the file.
So here is some code to try that out.
We have an important file, we open it in append more.
And let's see if this file really is important.
"Important data - do not remove!"
Yes, that sounds important!
We have to be careful here.
So we open this file in append mode and then we write to the file using the left shift operator.
We only use the write member function for low-level work, which we do not need here.
So let's run this program.
So the program has run. It has written to the file, we presume, and let's see if our important data is
still there.
Phew!
So there we are. "Important data - do not remove!"
So that is the data that was there before. And then we have "some more data" that we wrote at the end.
So that has worked. Good.
Instead of text mode, we can use binary mode, so the data in the file will have exactly the same bit
patterns as the data in memory.
So if we store the number 42 in a binary file, it will be stored as a binary number, which has
the equivalent to 42. The decimal 42, binary 101010.
If we used text mode, that would be stored as two separate characters, one representing '4', and one
representing '2'.
Binary mode is more complicated than text mode. It is low level, and it is easy to get things wrong.
You could also have problems when you try to take binary files from one computer to another.
If the computer that the file was written on has a different architecture from the computer that's opening
the file, it may not read the data correctly. Or even the same compiler with different settings, because
optimisation can change the way that the data is laid out.
So generally, you should avoid binary data.
However, there are some cases where it is important. If you are working with data, which is naturally
binary.
If you're working with file formats, so things like image files, media files, videos and so on.
And we will have an example of using binary files later on.
There are some other file modes. Truncate will always use truncate mode. In will open the file for input.
So we have ifstream, which is an input stream and ofstream, which is an output file stream.
There is also an fstream which is a general file stream, and you can use it for either.
So you can use in and out to say whether you want to use it for reading or writing or both.
So in will open it for input, out will open it for output. And that will also put it into truncate mode even
if you did not ask for it.
There is also ate or at 'e'.
I do not know how you are supposed to pronounce it!
This is similar to append.
So it'll preserve the existing data in the file.
And by default, if you write data, it will appear after the end of the file.
However, you can also write the output somewhere else in the file if you want to, which you cannot
do with append.
Append always has to go at the end of the file.
If he wants to combine different modes, these are just bitmasks, so we can use bitwise 'or', the
vertical bar, to combine them.
So if we have an fstream and we want to open it for output in append mode, then we combine the out and
append modes.
So this will open "important.txt" for output, in append mode.
So that is exactly equivalent to the way that we were using the file in the example.
We can also combine in and out with an fstream, and that will give us an fstream, that can both read from a file
and write to it.
If we do that, the file is not going to be truncated.
Usually when you do this, you want to read from the file before you write to the data, so it does not
make sense to overwrite the data before you look at it.
If you do want to truncate it, then you can combine that as well, so we are opening "both.txt" for
input and output in truncate mode.
And then finally, there are some restrictions on how you can use mode.
You can only use out with fstream and ofstream.
You cannot use it with input stream, obviously, and you cannot use in with an [output] stream.
Trunc is only available in output mode and you cannot use append and trunc together.
If you do use app, the file will always be opened in output mode.
So there we are!
That's it for this video.
I'll see you next time, but meanwhile, keep coding!