File Handling in C
File Handling in C
Memory is volatile and its contents would be lost once the program is terminated. So if we need the
same data again, it would have to be either entered through the keyboard again or would have to be
regenerated programmatically. Obviously both these operations would be time consuming. At such
times it becomes necessary to store the data in a manner that can be later retrieved and displayed
either in part or in whole. This medium is usually a ‘file’ on the disk. All data stored on the disk is in
binary form. How this binary data is stored on the disk varies from one OS to another. However, this
does not affect the C programmer since he has to use only the library functions written for the particular
OS to be able to perform input/output. It is the compiler vendor’s responsibility to correctly implement
these library functions by taking the help of OS.
File Operations
There are different operations that can be carried out on a file. These are:
➢ Creation of a new file
➢ Opening an existing file
➢ Reading from a file
➢ Writing to a file
➢ Moving to a specific location in a file (seeking)
➢ Closing a file
Now go through the following program before the discussion of file operation modes. The program will
read a file and display its contents on the screen.
# include "stdio.h"
main( )
{
FILE *fp ;
char ch ;
clrscr();
fp = fopen ( "text.txt", "r" ) ;
while ( 1 )
{
ch = fgetc ( fp ) ;
if ( ch == EOF )
break ;
printf ( "%c", ch ) ;
}
fclose ( fp ) ;
getch();
}
On execution of the above program it displays the contents of the file ‘text.txt’ on the screen. Suppose
you have a stored file in your laptop under C drive named text.txt (path: c:\text.txt).The content in the
file is “I love my India”. Then output of the above program will be “I love my India”, which will be
displayed on the screen.
"r" Searches file. If the file is opened successfully fopen( ) loads it into memory and sets up a pointer
which points to the first character in it. If the file cannot be opened fopen( )returns NULL. Operations
possible – reading from the file.
"w" Searches file. If the file exists, its contents are overwritten.If the file doesn’t exist, a new file is
created. Returns NULL, if unable to open file. Operations possible – writing to the file.
"a" Searches file. If the file is opened successfully fopen( ) loads it into memory and sets up a pointer
that points to the last character in it. If the file doesn’t exist, a new file is created. Returns NULL, if
unable to open file. Operations possible - adding new contents at the end of file.
"r+" Searches file. If is opened successfully fopen( ) loads it into memory and sets up a pointer which
points to the first character in it. Returns NULL, if unable to open the file. Operations possible - reading
existing contents, writing new contents, modifying existing contents of the file.
"w+" Searches file. If the file exists, its contents are overwritten. If the file doesn’t exist a new file is
created. Returns NULL, if unable to open file. Operations possible - writing new contents, reading them
back and modifying existing contents of the file.
"a+" Searches file. If the file is opened successfully fopen( ) loads it into memory and sets up a pointer
which points to the first character in it. If the file doesn’t exist, a new file is created. Returns NULL, if
unable to open file. Operations possible - reading existing contents, appending new contents to end of
file. Cannot modify existing contents.
Opening a File
Before we can read (or write) information from (to) a file on a disk we must open the file. To open the
file we have called the function fopen( ). It would open a file “text.txt” in ‘read’ mode, which tells the C
compiler that we would be reading the contents of the file. Note that “r” is a string and not a character;
hence the double quotes and not single quotes. In fact fopen( ) performs three important tasks when
you open the file in “r” mode:
➢ Firstly it searches on the disk the file to be opened.
➢ Then it loads the file from the disk into a place in memory called buffer.
➢ It sets up a character pointer that point to the first character of the buffer.
Why do we need a buffer at all? Imagine how inefficient it would be to actually access the disk every
time we want to read a character from it. Every time we read something from a disk, it takes some time
for the disk drive to position the read/write head correctly. On a floppy disk system, the drive motor has
to actually start rotating the disk from a standstill position every time the disk is accessed. If this were to
be done for every character we read from the disk, it would take a long time to complete the reading
operation. This is where a buffer comes in. It would be more sensible to read the contents of the file into
the buffer while opening the file and then read the file character by character from the buffer rather
than from the disk.
Same argument also applies to writing information in a file. Instead of writing characters in the
file on the disk one character at a time it would be more efficient to write characters in a buffer and
then finally transfer the contents from the buffer to the disk. To be able to successfully read from a file
information like mode of opening, size of file, place in the file from where the next read operation would
be performed, etc. has to be maintained. Since all this information is inter-related, all of it is gathered
together by fopen( ) in a structure called FILE. fopen( ) returns the address of this structure, which we
have collected in the structure pointer called fp. We have declared fp as
FILE *fp ;
The FILE structure has been defined in the header file “stdio.h” (standing for standard input/output
header file). Therefore, it is necessary to #include this file.
#include "stdio.h"
main( )
{
FILE *fp ;
fp = fopen ( "PR1.C", "r" ) ;
if ( fp == NULL )
{
puts ( "cannot open file" ) ;
exit( ) ;
}
}
➢ The characters in the buffer would be written to the file on the disk.
➢ At the end of file a character with ASCII value 26 would get written.
➢ The buffer would be eliminated from memory.
# include "stdio.h"
Void main( )
{
FILE *fp ;
char ch ;
int nol = 0, not = 0, nob = 0, noc = 0 ;
fp = fopen ( "PR1.C", "r" ) ;
while ( 1 )
{
ch = fgetc ( fp ) ;
if ( ch == EOF )
break ;
noc++ ;
if ( ch == ' ' )
nob++ ;
if ( ch == '\n' )
nol++ ;
if ( ch == '\t' )
not++ ;
}
fclose ( fp ) ;
printf ( "\nNumber of characters = %d", noc ) ;
printf ( "\nNumber of blanks = %d", nob ) ;
printf ( "\nNumber of tabs = %d", not ) ;
printf ( "\nNumber of lines = %d", nol ) ;
}
A File-copy Program
We have already used the function fgetc( ) which reads characters from a file. Its counterpart is a
function called fputc( ) which writes characters to a file. As a practical use of these character I/O
functions we can copy the contents of one file into another, as demonstrated in the following program.
This program takes the contents of a file and copies them into another file, character by character.
#include "stdio.h"
main( )
{
FILE *fs, *ft ;
char ch ;
fs = fopen ( "pr1.c", "r" ) ;
if ( fs == NULL )
{
puts ( "Cannot open source file" ) ;
exit( ) ;
}
ft = fopen ( "pr2.c", "w" ) ;
if ( ft == NULL )
{
puts ( "Cannot open target file" ) ;
fclose ( fs ) ;
exit( ) ;
}
while ( 1 )
{
ch = fgetc ( fs ) ;
if ( ch == EOF )
break ;
else
fputc ( ch, ft ) ;
}
fclose ( fs ) ;
fclose ( ft ) ;
}
I hope most of the stuff in the program can be easily understood, since it has already been dealt with in
the earlier section. What is new is only the function fputc( ). Let us see how it works.
Writing to a File
The fputc( ) function is similar to the putch( ) function, in the sense that both output characters.
However, putch( ) function always writes to the VDU, whereas, fputc( ) writes to the file.
Which file? The file signified by ft in the the above program . The writing process continues till all
characters from the source file have been written to the target file, following which the while loop
terminates. Note that our sample file-copy program is capable of copying only text files. To copy files
with extension .EXE or .COM, we need to open the files in binary mode.
Below is a sample program in which we will receive strings from keyboard and write them to a file
#include "stdio.h"
main( )
{
FILE *fp ;
char s[80] ;
fp = fopen ( "POEM.TXT", "w" ) ;
if ( fp == NULL )
{
puts ( "Cannot open file" ) ;
exit( ) ;
}
printf ( "\nEnter a few lines of text:\n" ) ;
while ( strlen ( gets ( s ) ) > 0 )
{
fputs ( s, fp ) ;
fputs ( "\n", fp ) ;
}
fclose ( fp ) ;
}
Note that each string is terminated by hitting enter. To terminate the execution of the program, hit
enter at the beginning of a line. This creates a string of zero length, which the program recognizes as the
signal to close the file and exit. We have set up a character array to receive the string; the fputs( )
function then writes the contents of the array to the disk. Since fputs( ) does not automatically add a
newline character to the end of the string, we must do this explicitly to make it easier to read the string
back from the file.
The function fgets( ) takes three arguments. The first is the address where the string is stored, and the
second is the maximum length of the string. This argument prevents fgets( ) from reading in too
long a string and overflowing the array. The third argument, as usual, is the pointer to the structure FILE.
When all the lines from the file have been read, we attempt to read one more line, in which case fgets( )
returns a NULL.