Data Files
Many applications require that information be written to or read from an auxiliary memory
device. Such information is stored on the memory device in the form of data files. Thus data
files allow us to store information permanently, to access and alter that information whenever
necessary. In C, an extensive set of library functions is available for creating and processing data
files.
There are two different types of data files, called stream-oriented (or standard) data files,
and system-oriented (or low-level) data files. Stream-oriented data files are generally easier to
work with and are therefore more commonly used.
Stream-oriented data files can be subdivided into two categories: text files and unformatted
data files. The text file consists of consecutive characters. These characters can be interpreted as
individual data items, or as components of strings or numbers. The manner in which these
characters are interpreted is determined either by the particular library functions used to transfer
the information, or by format specifications within the library function.
The unformatted data files organize data into blocks containing contiguous bytes of
information. These blocks represent more complex data structures, such as arrays and structures.
A separate set of library function is available for processing these data files. These library
functions provide single instructions that can transfer entire arrays or structures to or from data
files.
System-oriented data files are more closely related to the computer’s operating system than
stream-oriented data files. They are somewhat more complicated to work with though their use
may be more efficient for certain kinds of applications. A separate set of procedures, with
accompanying library functions, is required to process such data files.
There is also another type of file called binary file. These files are useful to handle file
containing machine language contents, for example .exe or .com files. The files which are stored
in binary format differ significantly from data files.
Why Data Files
Programs without data files accept input data from the keyboard at the time of execution and
write output to the monitor. This type of I/O is called console I/O. The main limitation of this
approach is that it is very difficult to handle a large volume of data. For large volume of data,
It takes a lot of time to enter the entire data.
If the same data is to be entered again at some later stage, again we have to enter the
same data.
If we exit from the program, all the data will evaporate.
Using data files enable us to save our data permanently to disk and retrieve them whenever we
want.
Opening and Closing a Data file
When working with a stream-oriented data file, the first step is to establish a buffer area, where
information is temporarily stored while being transferred between the computer’s memory and
the data file. This buffer area allows information to be read from or written to the data file more
rapidly than would otherwise be possible. This buffer area is established by writing
FILE *ptvar;
1
Where FILE (uppercase letters required) is a special structure type that established the buffer
area, and ptvar is a pointer variable that indicates the beginning of the buffer area. The pointer
ptvar is often referred to as a stream pointer, file pointer or simply stream.
A data file must be opened before it can be created or processed. This associates the file
name with the buffer area. It also specifies how the data file will be utilized, i.e., as a read-only
file, a write-only file, or a read/write file. The library function fopen is used to open a file. This
function is typically written as
ptvar = fopen(file-name, file-type);
Where file-name and file-type are strings that represent the name of the data file and the manner
in which the data file will be utilized. The file-type must be one of the strings as shown below.
These are also called file opening modes.
File-Type Meaning
“r” Open an existing file for reading only.
“w” Open a new file for writing only. If a file with the specified file name currently
exists, it will be destroyed and a new file created in its place.
“a” Open an existing file for appending (i.e., for adding new information at the end of
the file). A new file will be created if the file with the specified file name does not
exist.
“r+” Open an existing file for both reading and writing.
“w+” Open a new file for both reading and writing. If a file with the specified file name
currently exists, it will be destroyed and a new file created in its place.
“a+” Open an existing file for both reading and appending. A new file will be created if
the file with the specified file name does not exist.
The fopen function returns a pointer to the beginning of the buffer area associated with the file. A
NULL value is returned if the file cannot be opened for some reason.
Finally, a data file must be closed at the end of the program. This can be accomplished with
the library function fclose. The syntax is
fclose(ptvar);
Reading and Writing a Data file
Normally files are used for one of the two purposes – reading or writing. To write data into a
data file, we use fprintf function. For example, the program below writes characters A to Z each
in a separate line in an output file named “output.dat”.
#include<stdio.h>
#include<conio.h>
#define NULL 0
void main() {
int i;
FILE *fp;
fp = fopen("output.dat", "w");
if(fp == NULL)
printf("\nERROR - Cannot open the destination file\n");
else {
for(i=65; i <= 90; i++)
fprintf(fp, "%c\n", i); //writes data to the data file
2
fclose(fp);
}
getch();
}
To read data from a data file, we use fscanf function. For example, the following program reads
the contents of a data file on a character-by-character basis, and displays them on the screen.
#include<stdio.h>
#include<conio.h>
#define NULL 0
void main() {
char ch;
FILE *fp;
fp = fopen("output.dat", "r");
if(fp == NULL)
printf("\nERROR - Cannot open the destination file\n");
else {
fscanf(fp, "%c", &ch);
while(!feof(fp)) { //continues while loop until end of file
printf("%c", ch);
fscanf(fp, "%c", &ch);
}
fclose(fp);
}
getch();
}
If character inputs are to be read from the file, getc and fgetc can also be used instead of fscanf
statement. Similarly, to write data into a file, we can use putc and fputc instead of fprintf
statement. For example, the program below uses getc and putc to copy contents from a file
named “input.dat” into a file named “output.dat”. You can also use fgetc and fputc instead of
getc and putc.
#include<stdio.h>
#include<conio.h>
#define NULL 0
void main() {
FILE *fpin, *fpout;
char ch;
fpin = fopen("input.dat", "r");
if(fpin == NULL)
printf("\nERROR - Cannot open the destination file\n");
else {
fpout = fopen("output.dat", "w");
if(fpout == NULL)
printf("\nERROR - Cannot create the destination file\n");
else {
while(!feof(fpin)) {
3
ch = getc(fpin);
putc(ch,fpout);
}
}
}
fcloseall(); //close all open files
getch();
}
Data files consisting entirely of strings can often be created and read more easily with programs
that utilize special string-oriented library functions. We can use fgets, and fputs to read and write
strings with data files. For example,
#include<stdio.h>
#include<conio.h>
#define NULL 0
void main() {
FILE *fpin, *fpout;
char str1[20];
char *str2;
fpin = fopen("input.dat", "r");
if(fpin == NULL)
printf("\nERROR - Cannot open the destination file\n");
else {
fpout = fopen("output.dat", "w");
if(fpout == NULL)
printf("\nERROR - Cannot create the destination file\n");
else {
while(!feof(fpin)) {
str2 = fgets(str1,10,fpin);
fputs(str2,fpout);
}
}
}
fcloseall(); //close all open files
getch();
}
Example – Program to read all numbers from the input file “values.dat” and store the average
of these numbers in an output file named as “average.res.”
#include<stdio.h>
#include<conio.h>
#define NULL 0
void main() {
FILE *fpin, *fpout;
float val, avg, sum = 0;
int count = 0;
fpin = fopen("values.dat", "r");
if(fpin == NULL)
4
printf("\nERROR - Cannot open the destination file\n");
else {
while(!feof(fpin)) {
fscanf(fpin, "%f", &val);
sum = sum + val;
count++;
}
}
avg = sum / count;
fpout = fopen("average.res", "w");
if(fpout == NULL)
printf("\nERROR - Cannot open the destination file\n");
else
fprintf(fpout, "Average=%f", avg);
fclose(fpin);
fclose(fpout);
getch();
}
Unformatted Data files
Some applications involve the use of data files to store blocks of data, where each block consists
of a fixed number of contiguous bytes. Each block will generally represent a complex data
structure, such as a structure or an array. The library functions fread and fwrite are intended to be
used in situations of this type. These functions are often referred to as unformatted read and write
functions. Similarly, data files of this type are often referred to as unformatted data files.
Each of these functions requires four arguments: a pointer to the data block, the size of the
data block, the number of data blocks being transferred, and the stream pointer. For example,
fread(&customer, sizeof(struct account), 1, fpt);
fwrite(&customer, sizeof(struct account), 1, fpt);
The program given below is used to write customer data (account number, account type, name,
and balance) to a data file named “customer.dat”.
#include<stdio.h>
#include<conio.h>
#define NULL 0
void main() {
struct account {
int acct_no;
char acct_type;
char name[10];
float balance;
};
struct account customer;
FILE *fpt;
char ch;
fpt = fopen("customer.dat", "w");
if(fpt == NULL)
printf("\nERROR - Cannot open the destination file\n");
else {
5
printf("Enter customers' information:\n");
do {
printf("Enter account number:");
scanf("%d",&customer.acct_no);
printf("Enter account type:");
scanf(" %c",&customer.acct_type);
printf("Enter name:");
scanf(" %[^\n]",customer.name);
printf("Enter balance:");
scanf("%f",&customer.balance);
fwrite(&customer,sizeof(struct account),1,fpt);
printf("Do you wnat to add another record?(y/n)");
scanf(" %c",&ch);
} while(ch != 'n');
}
fclose(fpt);
}
The program given below is used to read customer data (account number, account type, name,
and balance) from a data file named “customer.dat”.
#include<stdio.h>
#include<conio.h>
#define NULL 0
void main() {
struct account {
int acct_no;
char acct_type;
char name[10];
float balance;
};
struct account customer;
FILE *fpt;
fpt = fopen("customer.dat", "r");
if(fpt == NULL)
printf("\nERROR - Cannot open the destination file\n");
else {
fread(&customer,sizeof(struct account),1,fpt);
while(!feof(fpt)) {
printf("Account no = %d\n",customer.acct_no);
printf("Account type = %c\n",customer.acct_type);
printf("Customer name = %s\n",customer.name);
printf("Balance = %f\n",customer.balance);
fread(&customer,sizeof(struct account),1,fpt);
}
}
fclose(fpt);
getch();
}
6