In this video, we'll talk about the steps needed to write output to text files
using c++ streams.
In the following slides, I'll talk about the main classes and methods that we can use to write to files,
and then I'll go over a few examples in live code.
The two classes I'll discuss for text file output are fstream
and ofstream.
We must always include fstream,
then we declare a stream object of either fstream or ofstream type.
We then connect the stream object we just created to the file we want to write to in our
file system. Once the file is connected and open, we can write to it.
By default, c++ will create the file if it does not exist.
And if it does exist, the contents of the file will be truncated or removed
unless we state otherwise.
We can write the files in binary or text mode,
and we can use any of the stream manipulators that we've already learned about.
Then when we're done processing the file, we must close the file.
This is very important for output files
since it flushes any buffers that may not have been written out to the file yet.
It's pretty easy. In the next few slides, we'll discuss the details
of opening a file for output,
checking to make sure the file was opened correctly,
writing to the file in different ways and then closing the file.
It's important to remember that by default output files will be created if they don't exist.
But we have to make sure that if we provide a path along with the file name
when we open the file that that path must exist.
Otherwise, we'll get an error when creating the file.
If the file already exists then it will be overwritten or truncated
unless we specify that we want to append to the contents of the existing file.
Finally, we can write in text mode or in binary mode.
In this section, we're only concentrating on text mode.
So in this example, we're creating an object named outfile,
and we're using the fstream class as its type.
Notice that I'm also initializing the object as well.
The initializer takes two arguments. The first is the name of the file
as we've already seen with input files.
This can be very operating system and ide dependent.
So in CodeLite we're going to use dot dot slash so it puts the file in our parent directory.
The second parameter specifies the mode and properties of the file that's being opened.
In the first example, we're using stood ios out.
This means to open the file in output mode.
So we're able to write to it but not read from it.
By default, files are opened in text mode.
In the second example, we're opening the file in output mode and in binary mode.
This is necessary when we're writing non-text files that contain binary data.
Notice the vertical bar or pipe character between stood ios out
and stood ios binary, this is the bit-wise or operator.
And when we use it in context like this, it sets both output
and binary modes to true.
At this point, the file will be opened if it was found and truncated or will be created.
In this slide, we use the fstream class.
The fstream class can actually open a file for reading and writing at the same time.
We won't be doing that. But if you have a file that you need to read from and write to,
we can use the fstream class to do that.
In this slide, we'll be using the ofstream class as the type of out file.
Ofstream is used commonly for output files only.
We can create an ofstream object the same way we created an fstream object.
However, in the case of an ofstream object,
std ios out is optional since it's already the default.
So the first two declarations of outfile have the same effect.
There's another way to open the file that's commonly seen in code, we saw it with input files. So let's see those next.
When we open a file for output, we have a few choices as to how we want to open the file.
By default, the file is opened for truncation,
and we can explicitly specify that as in the first example.
If we want the output file open, but we want all further output to append to
the end of the file,
then we can use the stood ios app flag when we open the file.
Finally, we can use the std ios ate flag.
When we want to open a file that exists
and we want to set the initial position of the next right to the end of the existing file.
But we're free to move around using random access.
We aren't going to use random access files in this course.
We'll focus solely on text-based sequential files.
Now just as we saw with input files,
we can first create the stream object and then open it, so let's see that.
In this example, notice that we're creating out file
as an ofstream object but we haven't provided any file name to associate with it.
This is common use case since many times we don't know the file name
and we have to get it from the user or from some other resource at runtime.
Once we have the file name, we can then use the open method
on the stream object to open the file.
So we can say outfile.open and give it the file name
or outfile.open file name and any flags we need.
Now that we attempted to create the output stream and connect it to a file,
we have to be sure this was successful before we start writing to the file,
and we'll do that next.
The process here is exactly as it was with input file streams.
We have to be sure that the file was open successfully.
So we can call the is open method on the file stream object we created.
This returns a Boolean indicating whether the file is open for processing.
If we get back true, we're good to go. If we get back false, some error occurred.
If no error occur, then we can go ahead and write to the file.
Let's see another way that we can test to see if the file was opened successfully.
In this case, we can simply test the stream object itself.
If the stream object was not instantiated, then this will return false
and we can decide what to do next.
Otherwise, it's good to go, and we can proceed writing to the file.
Once we finish writing to the file, we have to close it.
This is a simple method call to the close method.
With output files, this is very important since it flushes out any buffers
that may not have been written out to file yet.
Okay. So now we know how to open a file, check to make sure that it's open and close it,
now let's write to it.
There are many ways to write to a file. In these examples, we're going to use text files.
The most common way is to use formatted output using the stream insertion operator.
So in this example, we have an integer, a double and a string and three variables.
And we want to write them out to our output file.
We can assume that outfile was created successfully.
All we have to do is use the insertion operator as we've been using all along with cout
except that we insert the values into outfile. That's it.
Very simple, very powerful.
Remember, the stream manipulators we learned about in the beginning of this section,
we can use them all as well to format our output however we want.
Also notice that endline flushes out any unwritten buffers.
So let's write a program that copies one text file to another.
We'll assume the existing file is myfile.txt,
and we want to copy it to another file named copy.txt.
First, we create an ifstream object in file and initialize it to our input file.
Then we create an ofstream object out file initialize it to our output file.
In this case, if the output file does not exist, it will be created.
If it does exist, it will be truncated.
We need to be sure that both files were open successfully,
so we check using two if statements and if there's any error we terminate.
In the next slide, we'll complete the program and actually do the copying.
So at this point, our input file and output files are open and ready for processing.
We can use a while loop with a get line to read the input file one line at a time
into the string variable line.
If the read was, successful, the while loop condition will be true and we write
the line to out file then we close both files. That's it.
Really, really easy to copy one file to another.
Okay. So let's see one more example. This time we'll use unformatted read and write,
and then we'll see some examples in live code.
In this example, again, we're using infile as an ifstream object and
out file as an ofstream object.
We go through the same steps necessary to open the files, check to be sure they're
open and so forth. And then in the next slide,
we'll do the actual copying, but this time in an unformatted manner, one character at a time.
So here in the while loop, we read a character from infile using the get method.
And if it's successful, we write that character to outfile using the put method.
When we reach the end of file, the loop terminates, and we close the files.
That's it. So there you go. Two different ways to copy text files.
One that's doing it one line at a time
and another one that's doing it one character at a time, using unformatted read and write.
Great. So now let's head over to the IDE, and we'll see some examples of creating and writing to text files.