22)

Program 21 - Reading and writing files

Program 21 Reading and writing files Source code - prog21.c prog21a.c
So far all the data in the programs has been either created in memory or entered by the user. As soon as any of the programs finish, the data is lost. There are many programs where data needs to be stored permanently so that it can be retrieved later. This permenant storage is performed on a disk, and the following two programs show, firstly how data can be written to disk, then retrieved later, using data files.

It isn't as difficult as you'd think, however it does use pointers which will be covered on the next page.

There are two seperate programs listed. The first program asks the user to enter his/her name and age, then writes this information to a file. This should be executed first to create a file that the second program can use to recover the data.

 

Program code- new parts shown in red

WRITING TO A FILE - prog21.c

#include <stdio.h>

void main(void)
{
FILE *fptr;
unsigned char name[100];
int age;

printf("Please enter your name : ");
gets(name);
printf("\nPlease enter your age : ");
scanf("%d",&age);
fptr=fopen("myfile.dat","wb");
if(fptr!=NULL)
{
fwrite(&age,sizeof(int),1,fptr);
fwrite(name,sizeof(unsigned char),100,fptr);
fclose(fptr);

printf("\nFile written to disk");
}
else
printf("\nCouldn't open the file for writing");
}


READING FROM A FILE - prog21a.c

#include <stdio.h>

void main(void)
{
FILE *fptr;
unsigned char name[100];
int age;

fptr=fopen("myfile.dat",
"rb");
if(fptr!=NULL)
{
fread(&age,sizeof(int),1,fptr);
fread(name,sizeof(unsigned char),100,fptr);

fclose(fptr);
printf("Stored name = %s\n",name);
printf("Stored age = %d\n",age);
}
else
printf("Couldn't open the file");
}

 

Description of the program code
Writing to a file

The FILE *fptr; line declares a variable called fptr as a "file pointer". Any variable name declared with an asterix ( * ) in front of it, is a pointer, which can be thought of as a signpost pointing to "something", in this case it will be a file. Pointers are covered in detail on the next page though.

Before a program can use a file it has to be opened, and when the program is finished using the file it has to be closed. You can open and close files freely within a program. The line fptr=fopen("myfile.dat","wb"); opens the file called myfile.dat for writing binary data to it ( "wb" ). After the file is opened successfully the fptr variable will hold the pointer to it, which can then be used to reference it later.

In the case of opening files for writing with "wb", the file will be created by the program. If the file already exists it will be overwritten and the previous contents lost. After opening a file with the fopen function ( whether for writing or reading ), the returned file pointer should always be checked to see if it was successful or not. If the file couldn't be opened the returned file pointer value will be NULL.

Once the file has been opened though, and the program has a variable containing a file pointer, which isn't NULL, then operations on the file can take place. The fwrite function performs the writing of data to the file. The contents of two variables are written to the file in the code above, first the age variable is written, then the name array variable.

The fwrite function takes four parameters. The first is a "pointer" ( again sorry ) to the variable that is to be written. Don't worry about the use of the word "pointer" again, it will be explained, the only thing to remember is that if the variable that is being written isn't an array, then put the & in front of the name, otherwise not.

The second parameter is the size in bytes of the variable. Each data type takes up a different amount of memory ( measured in bytes ). An unsigned char takes up a single byte of memory, whereas an int takes up either two or four bytes depending on the compiler and operating system it is running on. It is useful to know how many bytes each data type takes up, but there is a function called sizeof in C which calculates it for you.

The sizeof function takes a single parameter, the data type or structure, and returns back the number of bytes of memory that is used for it.

The third parameter in the fwrite function is the number of elements to write to the file. In the example, the first fwrite line writes a single integer variable to the disk, the second writes 100 unsigned char variables to the disk, because the name is stored as an array of 100 unisgned char's.

The fourth and final parameter for the fwrite function is a pointer to a file to write to. This was obtained earlier when the file was opened.

Finally the fclose(fptr); line closes the file as it will not be needed anymore. A program should always close a file after it has finished working with it. If the file needs opening again later, then the program is free to use the fopen function again.

Reading from a file

This is virtually the same as writing to a file, but with a few subtle differences.

Firstly when a file is opened for reading the fopen function is still used, but this time the "wb" is not specified, but "rb" ( read binary ). It is even more important when opening files for reading to check that the returned file pointer is not NULL. There are far more likely things that may cause this, like for example, a file that doesn't exist. You can write to a file that's not there as it will be created, but you can't read from a file that's not there.

The fread function is used to read information from a file, instead of the fwrite function like before, but the two are very similar, in fact the same ! The only thing to note is that data written sequentially in the files above, so it has to be read back in the same order it was written to.

After running the first program ( to write ) you should end up with a file called myfile.dat in the same folder ( directory ) where miracle C is stored on your hard disk. This file will either be 102 bytes long or 104 bytes long depending on whether the int is a 2 byte (16 bit) int or 4 byte (32 bit) int on your compiler and PC.

When specifiying filenames with the fopen function, you can include path and drive information. The programs above just specified a filename so they were stored in the current folder, which is the C compiler folder. The following line can be used to open a file for writing in the root folder of your hard disk.

fptr=fopen("c:\\myfile.dat","wb");

Notice the double backslash has to be used in exactly the same way as in the printf statement. The following shows two ways which you can specify the file be written to a folder on the disk ( in this example the windows folder ).

fptr=fopen("c:\\windows\\myfile.dat","wb");

or

fptr=fopen("c:\\windows/myfile.dat","wb");

With the second example it shows how a single forward slash can be used instead of a double backslash.

The three examples just shown all use an "absolute filename", but you can use relative file names as well. For example, if the generated program is running from the windows folder. You could write a file to the windows/system folder with the following :

fptr=fopen("system/myfile.dat","wb");

Besides the "wb" and "rb" file modes, there are a number of other less common file modes that can be used, for things like appending to files, opening a file as read/write or reading and writing text files. I don't often use them, if ever at all, but there is a full list in the miracle C language help .. look under header files -> stdio.h -> fopen for a full list.

Be very careful though when opening files, especially when they are open for writing. It is very easy to open files for writing that are essential to the operating system ( for example command.com, win.com etc.. ) .. writing over these files would mean that your computer would need formatting and windows re-installed, which would lose all the data on the hard disk. Only open files that are in your current working folder, or any folders that branch from it.

 

Summary
This page has shown how to both write to and read from files. This now means that programs can be produced where information is obtained from another source besides the user. It also means that things like user settings can be stored and retrieved and programs have a life that extends beyond the point where they start and finish.

Care has to be taken though when writing programs that use files as it is possible to damage existing files on your computer.

There's been a lot mentioned about "pointers" and it's been hard getting here without going into them in any detail, but it is probably the single most complicated part of C to understand which is why it has been left until the next page. Most of it will be theory though, but with an understanding of pointers, it should all click into place. They're interesting too because they give an insight into how the computer works at a low level.

It's getting close to the end now of learning C programming, almost everything has been covered !

 

Tasks

21.1) See if you can write the two programs above that use a structure to store the name and age, and use a single fwrite and fread line to write and read the data to an from a disk file.

 

Go back a page Continue on to next page >>

(c) J.C.Spooner 2001