Hello, and welcome back.
In this lecture, I want to talk about accessing files.
So files on disk have a name and the rules for naming the files are
determined by your operating system.
You may have to adjust the names depending on OS
your program is running.
If your program is running on windows versus Linux, the actual directory
structure is different as well.
So if you use forward slashers or backward slashes, you have
to adjust this in your program.
But for the most part, the names are relatively have the
same naming rules and so forth.
But there is the chance that you'd have to adjust it.
A program references a file through a file pointer or a stream pointer.
Since it works on more than just a file, you can actually, we mentioned
this earlier, but the standard io functions work on any device.
So it's called a file pointer, but it's really should be
referred to as a stream pointer.
You associate a file pointer with a file programmatically
when your program is run.
So what you end up doing is you'll create a pointer inside your
program, it'll be of type file and that's going to represent the file
when you read and write to it.
We use these file pointers as a more effective way to actually
point to the files as opposed to the name because the name
can be a little bit different.
The pointer will represent what it's actually pointing to.
And you can reuse the pointers, to point to different files on
different occasions, which, again, was represented by the file name.
A file pointer points to a structure type file that represents a stream.
You can actually go and look at the file struct to see
everything that's inside of it.
But it contains information such as whether you want to read or
write or update the file, the address of the buffer in memory
where you're storing data, a pointer to the current position in
the file for the next operation.
We mentioned the position is important because that's where
you're doing your writes and reads.
And you can set all this information inside the structure by using
input and output file operations.
The input output file operations, when you open a file, it's going
to actually specify whether you want to read or write.
And then also you can change the current position by using other
methods like seek and so forth that we're going to talk about.
If you want to use several files simultaneous in your program,
you have to create a separate file pointer for each file.
You can only reuse the file pointer if you're reading and
writing at different times.
There is a limit to the number of open files you can have at one open time.
You can look at the limit in the standard IO, there's a constant
defined f open max it all depends on again what operating
system you're running on.
But you usually do not want to create and open a ton of files at once.
Writing and reading the files is an expensive operation because
you're writing on the hard drive.
It's not as fast as writing the memory, so it takes time
and it can cause your program to be less responsive so.
You don't want to have 10 files open and writing at
10 files at the same time.
To open up a file, this would be the first step that you
do before you read and write.
So you want to associate a specific external file name with an entire
final pointer through a process referred to as opening the file.
The way that you open a file and see is you call f open function.
This will return the file pointer which you can then
use for reading and writing.
And again, the file pointer is going to point to a specific
external file that's on the disk.
F open is going to take the name of the file.
The f open is what you have to do before you do any reading/writing.
It's usually your first operation.
And as with most of these functions, they're all defined in standardio.h.
Here is the definition of the f open call.
You'll see that the return value is a file pointer, it's
all caps, the file structure.
So all caps file.
You'll then notice that it takes a couple parameters, it takes a name
and a mode and don't worry about this restrict that's just more C11 stuff.
It really just takes the character pointer to a name and a mode.
The first argument of the function is a pointer to a string that
that is the name of the file, so that will be inside double quotes.
You can specify the name explicitly or use a character pointer that contains
the address of the character string.
So all this is saying is you could create a character string and put
assign it to literal text and then pass in the string to the function
or you can put in inside the double quotes right inside the function call.
You can obtain the file name through the command line as input
from the user as well or define it as a constant your program.
If it's always the same file you're reading writing to and
the name doesn't matter, you can just refer to as a constant.
If your program is more flexible, it can get input from the user to say
what you want to read or write to.
The second argument to the f open function is a character string
that represents the file mode.
This specifies what you want to do with the file, whether you want to
read it, whether you want to write to it, whether you want to append to it.
A file mode specification is a character string between
double quotes, and I'll show you some of the ones that we're
going to end up using a lot of.
Assuming the call to f open is successful, it will return
that file pointer, all caps.
And then you can use this file pointer to call other input/output
functions in standard IO header, and we're going to go through those when
we go through reading and writing or you can also get the position
using that pointer to change the position of where you are in the file.
If the file cannot be opened for some reason, f open
is going to return null.
So what this means is before you start doing any reading or writing,
make sure that the pointer is not equal to null, another if check.
Here are the file modes that I mentioned.
The file modes, remember, are the second parameter to the f open call.
This is what specifies what you want to do with the file, and
it's all inside double quotes.
So if you do a w, that means you want to open the text file for writing.
If you do an a, that means you want to open the text file for appending,
all writes are to the end of the file.
If you do an r, it opens up the text file for reading.
If you add a plus to any of these, it will basically create
the file if it doesn't exist.
So if you open up a w plus file, it will open it up for update and
it will truncate the file to zero if it exists or it could create
a new file if it doesn't exist.
With the other ones, it's going to write or read um
and the file has to exist.
Same with a plus, it's going to open it up for appending, for an update,
to the end of the existing file or create the file if it doesn't exist.
And the r plus will open up the text file for update, it's
not going to create the file there because it will be empty.
So the reading is just for both reading and writing
when you see the r plus.
A little different than the other pluses where they're actually
creating the file it doesn't exist.
Write mode.
If you want to write to an existing text file with the name
myfile.txt, you would create your file pointer, all caps.
Set it to null, initialize it the null.
And then you would maybe create your file as another character
pointer, myfile.txt or you could pass that in as the first parameter,
and then you just say f open.
F open file name and then w inside double quotes that opens the file for
writing and it returns a file pointer.
That's why you have p file on the left of the assignment.
You then want to check to make sure p file's not equal to null.
Because if it's null, if it failed to open for any reason
maybe the file name was wrong or it didn't exist, then you
wouldn't be able to write to it.
So you always want to do the f check and print out some
information if it doesn't open.
This code will open up the file and it will associate the file
with the name myfile.txt with your file pointers fp file.
The mode w means we can only write to the file, you cannot read from it.
If a file with the name my file that text does not exist, the
call to f open will create a new file with this name,
and that's for f open with the w option.
And so when we saw in the previous modes, w plus will create the
file if doesn't exist but it also truncates the file to zero.
That's the different with the w.
The w will create if it doesn't exist, but it's not
going to truncate it to zero.
So this is the standard way for opening up files, using that
w inside the double quotes.
If you only provide the file name without any path specification,
so that's what we did in this example, a path remember is
the name of the directories.
If you don't provide the name of the directories, it's going to assume that
that file is in the current directory wherever the program is executing.
If you want to actually open up a file somewhere else where
it's not actually located in the programs directory, then you
have to specify the entire path.
That's called the absolute path.
When you provide no path it's usually the relative path, it's relative
to where the program is running.
So you can specify either one, the absolute or the relative path, just
make sure you know where it's located and you're doing the right one.
Relative paths are usually better because then it's not dependent.
If somebody would have moved that file it's not dependent
on where it was moved.
And you can actually do a relative path, and you can go back
directories, so you can do a dot slash and that's relative to where
the program is running you're just going back a couple directories.
When you use an absolute path, it would actually be
something like c colon program files if you're on windows.
And if that file ever moved, the program would not be able to open it.
So on opening a file for writing the file link is truncated to
zero, and the position will be at the beginning of any existing
data for the first operation.
Any data that was previously written to the file will be lost and
overwritten by any write operations.
So again without providing the plus on it, it just means
you can't read and write.
This is write only.
W is right only.
W plus means you can read and write.
Append mode.
If you want to add to an existing text file rather than overwrite it
you can specify the a mode.
This is depending.
This positions the file at the end of any previously written data.
If the file doesn't exist, it creates a new one.
The example here is you just change the second parameter to
be an a inside double quotes, it will add to the end of myfile.txt.
And do not forget that you should always test the return
value for null each time.
You always want to do the if p file is not equal to null.
When you open a file in append mode, all the write operations
will be at the end of the data in the file in each write operation.
All write operations append data to the file, and you cannot
update the existing contents in this mode, it's all at the end.
In read mode we can open up the file to read a file.
We just use the r inside double quotes.
This is read only, you cannot write to the file.
If you do r plus you would be able to read and write.
So it looks like the other calls, you just do an f open, pass in the
name of the file and then r in double quotes that returns a file pointer.
We'll also position the file to the beginning of the data.
If you're going to just read the file, it must already exist.
You're not going to read an empty file.
So there's no option of creating the file it doesn't exist, it will
just be empty or you would get back the file opponent would be null.
If you try to open a file for reading it doesn't exist, it
will return the null pointer.
If it does exist and it's empty, you just will return no data.
You always want to check the value return from f open.
Again, reading that for the second time, it's important.
Because if it's a null pointer, your program is going to crash,
it's going to do something bad.
Renaming a file.
We know now how to open a file.
Opening a file is the first operation, you specify the
mode and the name of the file.
That gives you back the file pointer which you can now
use to do other things with.
Renaming a file is sometimes important.
It's very easy.
You just use the rename function.
It takes a old name and a new name as constant character
pointers, and it returns an int.
The integer that's returned will be zero if the name change was
successful and non-zero otherwise.
The file must not be open when you call rename.
Otherwise, it's going to fail because it's in use you can't
rename a file when it's in use.
So what you can do here is you can just say rename, pass in the old
file name and the new file name.
In this example, we're using a path to a file in windows.
And that you know it's windows because I see colon.
You also notice that the backslash is there twice.
The reason for that is because the backslash is a special character in c.
Backslash n is a line feedback.
Backslash r is a carriage return.
So the backslash has special meaning in the program.
So if you want to actually use the backslash for a path in a directory,
which is what windows does, you have to provide two of them.
And so here we're renaming a myfile.txt locating
the temp directory.
We rename it to my file underscore copy.text in attempt directory.
And if that is not equal to one, it will fail.
We just print out an output that says it failed.
Otherwise, your printout successful.
This is going to change the name of myfile.txt in the temp directory to my file copy.
If the file path is incorrect or the file does not exist, it's
not going to be able to rename.
You can also close a file and you want to do this whenever you open a file.
So when you're done with the file itself, you want to tell the
operating system to free up that file.
Remember, there's a limit to how many files you can
have open at any given time.
You can do this by calling the f close function.
F close accepts a file pointer as an argument.
Remember, the file pointer represents the file.
It returns an eof.
Eof is an int.
Returns eof if an error occurs.
Eof is a special character called the end of file character.
It's defined in standardio.h as a negative integer.
It's usually equivalent to negative one.
If f close was successful, it will return zero.
So you can check for eof for unsuccessful.
You just say f close pass in the pointer, you can then set the pointer
to null and the result of calling f close is that the connection
between the pointer, the p file and the physical file is broken.
P file can no longer be used to access the file for reading,
writing or appending or renaming.
If the file is being written to, the current contents of the output
buffer are written to the file to ensure that the data is not lost.
So you don't have any problems with data integrity, you're not going to
actually close the file if it was being written to in another thread.
So it's thread safe.
We haven't talked about threads, that's more advanced concept.
But it's where you can have multiple execution points in your program.
It's good programming practice to close a file as soon as you
have finished with it, just like it's good programming practice
to free memory when you're done with it, same for closing files.
It protects against output data loss.
You must also close a file before attempting to rename
it or remove it, it has to be closed it can't be opened.
How about deleting a file.
You can delete a file by invoking the remove function.
This is also declared in standardio.h.
All the file operations are declared in standard.ioh.
You can always go look at this header file if you want wherever
the c header files are installed.
So you just say remove name of the file.
Here you don't have to use the file pointer.
You can just say because the file doesn't have to
actually be open to remove it.
The same with the rename because you don't actually want the
files to be open because the rename or the remove will fail.
It's going to delete the file that has the name myfile.txt
from the current directory.
This is providing a relative path.
It's going to look for that file wherever the program is executing.
Otherwise, you need to provide an absolute path.
The file cannot be open when you try to delete it, just like rename.
You should always double check with operations that delete files.
You could wreck your system if you do not.
A delete is a very expensive, very hazardous operation.
Deleting files can cause problems.
So be careful.
All the information in this lecture had to do with accessing files,
how you can open up files, which is what you need to do before you
read and write, and also how you can delete and rename files and then
closing when you're done using them.
Everything is based off that file pointer.
So understand that file pointer and the structure it contains.
Pretty useful stuff.
The standard io header contains all the great information.
Next couple lectures, we're going to talk about reading and writing
to text files, actually adding data or adding or reading it.
Thank you. I hope this was helpful.