10.1 Introduction
Many applications require the
information to be written or read from an auxiliary memory device. Such
information is stored on the memory device in the form of a data file.
Thus, data files allow us to store information permanently, and to access and
alter that information whenever necessary.
In C, an extensive set of library
functions are available for creating and processing these files. There are two
different types of data files:
1.
Stream-oriented (or standard) data files
2.
System-oriented (or low-level) data files
Stream-oriented data files are
divided into two categories:
Text Files:
-consists of consecutive characters
-these characters can be interpreted as individual data items, or as
components of strings or numbers
Unformatted data files:
-organizes
data into blocks containing contiguous bytes of information
-these
blocks represents more complex data structures, such as array and structures.
System-oriented data files:
-are
more closely related to the computer's operating system
-more
complicated to work with
-A
seperate set of procedures, library functions are require to process these
files
Here, we will discuss only about
Stream-oriented data files.
The C file system is composed of
several interrelated functions. The most common of these are shown below. They
require the header file stdio.h to be included.
Name Function
fopen() Opens
a file
fclose() Closes a
file
putc() Writes
a character to a file
fputc() Same
as putc()
getc() Reads
a character from a file
fgetc() Same
as getc()
fgets() Seads
a string from a file
fputs() Writes
a string from a file
fseek() Seeks
to a specified byte in a file
ftell() Returns
the current file position
fprintf() Is to a
file what printf() is to the console
fscanf() Is to a
file what scanf() is to the console
feof() Return
true if end-of-file is reached
ferror() Return true if an error has occured
rewind() Resets
the file position indicator to the beginning
remove() Erases
a file
fflush() Flushes
a file
Table:
Commonly used C file system functions
The FILE Pointer
The FILE pointer is the common
thread that unites the C I/O system. A file pointer is a pointer to a structure
of type FILE. It points the information that defines various things about the
file, including its name, status, and the current position of the file.
Inorder to read or write files,
your program needs to use file pointers.
FILE
*fp;
Opening a file
Before we can write a file to
disk, or read it, we must open it. Opening a file establishes an understanding
between our program and the operating system about which file we are going to
access and how we are going to do it. We provide the operating system with the
name of a file and other information like whether we plan to read or write to
it.
Opening a file start with the
declaration of variable of type pointer to a file in the statement as:
FILE
*fptr;
Then we open the file with the
statement
fptr=fopen("name.txt","w");
Thus, fopen() function takes two
arguments. The first argument is the name of file to be opened and the second
argument is the mode in which file has to be opened.
The table below shows the legal
values for mode.
Mode Meaning
r Opens
a text file for reading. The file must exist.
w Create a text
file for writing. If the file exists, its contents will be written over. If does not exist it will be
created.
a Append
to a text file. Data will be added to the enf of an existing file, or a new
file will be created
r+ Opens
a text file for both reading and writing. The file must already exist.
w+ Opens
a text file for both reading and writing. If the file exists its contents are
written over.
a+ Opens
a text file for both reading and appending. If file does not exist it will be
created.
rb Opens a binary
file for reading.
wb Create a binary
file for writing
ab Append to a
binary file
r+b Opens a binary
file for read/write
w+b Create a binary
file for read/write
a+b Append or create a
binary file for read/write.
Table:
The legal values for mode
Note: Strings like "r+b"
may also be represented as "rb+"
Closing a file
The fclose()
function closes a stream that was opened by a call to fopen(). The fclose()
function has this prototype:
int
fclose(FILE *fp);
Where, fp is the file pointer
returned by the call to fopen(). A return value of zero signifies a successful
close operation. The function returns EOF if an error occurs. You can use the
standard function ferror() to determine and report any problems. Generally,
fclose() will fail only when a disk has been permanently removed from the drive
or there is no more space in the disk.
The opened file is closed with the
following statement:
fclose(fp);
10.2 Character input/Output
functions in file
getc(), putc(), fgetc(), and fputc() are charcter input output functions. As a
practical use of these character input output functions we can read line of
text in lowercase and convert it to uppercase, as demonstrated in the following
example.
use of getc( ) and putc( ) functions to read a line of
text in lowercase and store in data file after converting it to uppercase.
Example 1
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<ctype.h>
main()
{
char ch;
FILE *fp;
fp=fopen("file1.txt","a+");
if(fp==NULL)
{
printf("cannot open file");
fclose(fp);
exit(1);
}
do
{
ch=toupper(getchar());
putc(ch,fp);
}while(ch!='\n');
clrscr();
rewind(fp);
while((ch=getc(fp))!=EOF)
printf("%c",ch);
fclose(fp);
getch();
}
Coping contents of one file into another. This program
takes the contents of a text file and copies them into another text file
character by character
Example 2
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
main()
{
char ch;
FILE *fs,*ft;
fs=fopen("file1.txt","r");
if(fs==NULL)
{
printf("can not open source
file\n");
exit(1);
}
ft=fopen("file2.txt","w");
if(ft==NULL)
{
printf("Cannot open target
file");
fclose(ft);
exit(1);
}
while((ch=fgetc(fs))!=EOF)
fputc(ch,ft);
fclose(fs);
fclose(ft);
getch();
}
In this program file1.txt is a source file which is opened
in read mode and file2.txt is a destination file which is opened in write mode.
Using feof() function
The function feof() determines when the end of
the file has been encountered. The feof() function has this prototype:
int
feof(FILE *fp);
feof() returns true(1) if the end of the file has been
reached; otherwise, it returns 0.
e.g.
while(!feof(fp))
ch=getc(fp);
The operation of feof() is illustrated in the Example 3.
10.3 String input/output
function in file
Reading or writing strings of characters from and to files
is easy as reading and writing individual characters. fputs() and fgets() are
string(line) input/output function in C.
The fputs() function writes the string pointed
to by string variable to the specified stream. It returns EOF if an error
occurs.Since fputs() does not automatically add a new line character to the end
if the string; we must do this explicitly to read the string back from the
file.
The fgets() function reads a string from the
specified stream until either a new line character is read or length-1
character have been read. The function fgets() takes three arguments: the first
is the address where the string is stored, the second is the maximum length of
the string, and the third is the pointer to the structure FILE. When all the
lines from the file have been read, if we attempt to read one more time it will
return NULL.
Here is a sample program that writes strings to a file using
the function fputs() and reads string from the file using fgets() function.
Example 3
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>
main()
{
char string[25];
FILE *fp;
fp=fopen("file3.txt","a+");
if(fp==NULL)
{
puts("can not open
file");
exit(1);
}
do
{
printf("Enter a string
to store in data file:");
gets(string);
strcat(string,"\n");
//add new line, since fgets() does not automatically add new line character to
the end of the string
fputs(string,fp);
}while(*string!='\n');
rewind(fp);
while(!feof(fp))
{
fgets(string,2,fp);
puts(string);
}
fclose(fp);
getch();
}
In this example, while writing to a data file do while loop
is used, which allows you to enter any number of strings. To stop entering you
have to press enter key at the beginning (i.e. new line character should appear
at the beginning). Similarly strings can be read from the data file until the
end-of-file is reached.
Using rewind() function
The rewind() function resets the file position
indicator to the beginning of the file specified as its arguments. That is, it
"rewinds" the file. Its protype is
void
rewind(FILE *fp);
where fp is a valid file pointer.
In Example 1 and Example 3 the rewind()
function is used after input is complete to move file position indicator at the
beginning so that data can be read from the beginning.
10.4 Formatted Disk I/O
Functions in file
For formatted reading and writing of characters, strings,
integers, float, there exist two functions: fscanf() and fprintf(). Here is a
sample program which illustrates the use of these functions.
Program to write information to a file and read from
using formatted Input/Output.
Example 4
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
main()
{
char choice;
char name[40];
int age;
float height;
FILE *fp;
fp=fopen("myname.txt","w+");
do
{
printf("\nEnter
name:");
scanf("%s",name);
fflush(stdin);
printf("\nEnter
age:");
scanf("%d",&age);
fflush(stdin);
printf("\nEnter
height:");
scanf("%f",&height);
fflush(stdin);
printf("\nDo you wish to
continue:");
scanf("%c",&choice);
fprintf(fp,"%s\t%d\t%f",name,age,height);
}while(choice=='Y'||choice=='y');
rewind(fp);
while(!feof(fp))
{
fscanf(fp,"%s%d%f",name,&age,&height);
printf("\n%s\t%d\t%0.2f",name,age,height);
}
fclose(fp);
getch();
}
In this program the function fprintf() writes
the values of three variables to the file. This function is similar to
printf(), except that a FILE pointer is included as the first argument.The
function fflush() is designed to remove or flush out any data remaining
in the buffer. The argument to fflush() must be the buffer which
we want to flush out. Here we use 'stdin', which means buffer related with
standard input device, the keyboard. The fscanf() function is
used to read the data from the disk. This function is similar to scanf(),
except that, as with fprintf(), a pointer to FILE is included as
the first argument.
10.5 Record Input/Output
functions in file
In above cases we found that
storing number in the format provided by formatted Input/Output functions take
up a lot of disk space, because each digit is stored as a character. Similarly,
formatted Input/Output has another problem: there is not direct way to read and
write complex data types such as arrays and structures. Arrays can be handled
but inefficiently by writing each array element one at a time.
A possible solution for this
problem is record input/output, which is sometimes called "block
input/output". Record input/output writes number to disk file in binary(or
"untranslated") format, so that integers are stored in 4 bytes,
floating point number in 4 bytes, and so on for the other numerical types.
Record I/O also permits writing any amount of data at once. Array, structures,
and other data constructions can be written with a single statement. The
functions used for this purpose are fread() and fwrite().
fread() and fwrite()
To read and write data types that are longer than one byte,
the C file system provides two functions: fread() and fwrite().
These functions allow the reading and writing of blocks of any type of data (they are used for
reading/writing records with binary file). The following program writes and
reads data to and from binary file.
Program to write and read the data of structure to and
from data file
Example 5
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
struct employee
{
char name[40];
int age;
float basicsal;
};
main()
{
struct employee e;
FILE *fp;
char choice;
fp=fopen("employee.txt","a+b");
if(fp==NULL)
{
printf("Can not open
file!");
exit(0);
}
do
{
printf("Enter name,age,
and basic salary:\n");
scanf("%s%d%f",e.name,&e.age,&e.basicsal);
fwrite(&e,sizeof(e),1,fp);
fflush(stdin);
printf("Add another
record(Y/N)");
scanf("%c",&choice);
}while(choice=='Y'||choice=='y');
rewind(fp); //Moves file
pointer to the beginning to read from the beginning
while(!feof(fp))
{
fread(&e,sizeof(e),1,fp);
printf("\n%s\t%d\t%f",e.name,e.age,e.basicsal);
}
fclose(fp);
getch();
}
The information obtained about the employee from the
keyboard is placed in the structure variable e. Then, the following
statement writes the structure to the file.
fwrite(&e,sizeof(e),1,fp);
Here, the first argument is the address of the structure to
be written to the disk. The second argument is the size of the structure in
bytes. Instead of counting the bytes occupied by the structure ourselves, we
let the program do it for us by using sizeof() operator, which
gives the size of the variable in bytes. The third argument is the number of
such structures that we want to write at one time. In this case, we want to
write only one structure at a time. The last argument is the pointer to the
file we want to write to.
The fread() function causes the data read from
the disk to be placed in the structure variable e. The format of fread()
is same as fwrite(). The function fread() returns
the number of records read. If we have reached the end of file, since fread()
can not read anything, it returns 0.
Program on reading and wrting arrays with record I/O
functions
Example 6
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
int
table[10]={1,2,3,4,5,6,7,8,9,10};
main()
{
FILE *ftp;
ftp=fopen("table.txt","wb+");
if(ftp==NULL)
{
printf("Can not open
file");
exit(0);
}
else
fwrite(table,sizeof(table),1,ftp);
printf("Data has been
written on file successfully....\n");
rewind(ftp);
while(!feof(ftp))
fread(table,sizeof(table),1,ftp);
for(int i=0;i<10;i++)
{
printf("%d\t",table[i]);
}
fclose(ftp);
getch();
}
ftell() function
ftell() returns the current file pointer for stream. The
offset is measured in bytes from the beginning of the file (if the file is
binary).
Its prototype is
long
int ftell(FILE *stream);
The value returned by ftell can be used in a subsequent call
to fseek.
ftell returns the current file pointer position on success.
It returns -1L on error and sets the global variable errno to a positive value.
In the event of an error return the global variable errno is
set to one of the following values:
EBADF Bad
file pointer
ESPIPE Illegal
seek on device
/* ftell example */
#include <stdio.h>
main()
{
FILE *stream;
stream = fopen("MYFILE.TXT",
"w+");
fprintf(stream, "This is a test");
printf("The file pointer is at byte
%ld\n", ftell(stream));
fclose(stream);
getch();
}
fseek() function
Repositions a file pointer on a stream.
fseek() sets the file pointer associated with
stream to a new position that is offset bytes from the file location given by
origin.
Syntax:
int
fseek(FILE *stream, long offset, int origin);
offset is the number of bytes from the origin that will
become the new current position.
For text mode streams offset should be 0 or a value returned
by ftell().
origin must be one of the values 0, 1, or 2 which represent
three symbolic constants (defined in stdio.h) as follows:
Constant Origin File location
SEEK_SET 0 File beginning
SEEK_CUR 1 Current file pointer
position
SEEK_END 2 End-of-file
After fseek the next operation on an update file can be
either input or output.
Return Value
fseek returns 0 if the pointer is successfully moved and
nonzero on failure.
Random File Processing
Example 7
#include<stdio.h>
#include<conio.h>
struct employee
{
char name[10];
char address[15];
long int phone;
char qualification[10];
}emp[5],emp1;
main()
{
int
endposition,current_position,total_no,n,i;
FILE *fptr;
fptr=fopen("random.txt","a+");
char choice;
for(i=0;i<5;i++)
{
printf("Enter the name:");
scanf("%s",emp[i].name);
printf("Enter the address:");
scanf("%s",emp[i].address);
printf("Enter Phone No:");
scanf("%ld",&emp[i].phone);
printf("Enter Qualification:");
scanf("%s",emp[i].qualification);
fwrite(&emp[i],sizeof(struct
employee),1,fptr);
clrscr();
}
rewind(fptr);
fseek(fptr,0,SEEK_END);
endposition=ftell(fptr);
total_no=endposition/sizeof(struct
employee);
do
{
printf("There are %d structures,which u
want to view?",total_no);
scanf("%d",&n);
current_position=(n-1)*sizeof(struct
employee);
fseek(fptr,current_position,SEEK_SET);
fread(&emp1,sizeof(struct
employee),1,fptr);
printf("\n The name is
%s\n",emp1.name);
printf("The address is %s\n",emp1.address);
printf("The phone no is
%ld\n",emp1.phone);
printf("The qualification is
%s\n",emp1.qualification);
fflush(stdin);
printf("Do u want to see some other
records(Y/N):");
scanf("%c",&choice);
clrscr();
}while(choice=='Y'||choice=='y');
fclose(fptr);
getch();
}
End of Chapter Ten
[ Note: If you have any problems regarding this then you can post the
problem in comment box. we will try to solve this here. Or if you know
any solution, you can also help :) ]