The best programs are written so that computing machines can perform them quickly and so that human beings can understand them clearly. A programmer is ideally an essayist who works with traditional aesthetic and literary forms as
well as mathematical concepts, to communicate the way that an algorithm works and to convince a reader that the results will be correct. Donald E. Knuth

File Handling in C

Files are a means to store data in a storage device. C file handling provides a mechanism to store output of a program in a file and read from a file on the disk. So far, we have been using printf to write output of a program on to the screen and scanf to read input from keyboard. Now we will be looking at functions which allows us to create, open and write to a text or binary files in order to permanently store the output of a program to a file or reading input from a file.

Opening a File
In order to open a file, we need to use fopen( ) function. If the file is opened successfully, we assign a file pointer to the file to perform reading and writing operations. A file can be opened in different modes depending on requirement. Function to open a file i.e fopen( ) takes two arguments : char *filename and const char *mode. C supports the following file open modes :

ModeExplanation
" r "Open a file for reading
" w "Open a file for writing. If the file already exists, then the contents are overwritten.
" a "Appends data to the end of the file
" r+ "Opens a file for reading and writing. We can read and modify existing contents and write new contents.
" w+ "Opens a file for reading and writing. If the file exists, then its contents are overwritten. We can write new contents, read and modify them.
" a+ "Opens a file for reading and writing data to the end. We cannot modify existing data.

If a file is opened in any of the write modes and the file doesn't exist, then a new file is created. If the file is opened in read mode and the file is not found, then NULL is returned by the fopen( ) function. If the "file open" operation fails for any other reason, then also NULL is returned. For handling binary files, we need to append character ' b ' to the file open modes. For e.g, rb , wb , r+b , etc.

File Read / Write Operations
Open a file for writing :

/*
 * This program writes strings to a file 
 */
#include <stdio.h>

int main() {
    /* "FILE" is structure and we declare a pointer to variable of "FILE" type
       to point to the opened file */
    FILE *fp;
    fp = fopen("file.txt", "w"); /* opened a file for writing */
    if (fp == NULL) {
       printf("\nError : Can't open file ... ");
    }
    else { /* file is opened successfully */
       fprintf(fp, "This is a line\n"); /*write a line to a file using fprintf*/
       fputs("This is another line\n", fp); /* write to a file using fputs */
    }
    fclose(fp); /* close the file */
    printf("Two lines written to a file\n");
    return 0;
}
Run this program in your system to write to a file  

Open a file for reading :

/*
 * This program reads strings from a file 
 */
#include <stdio.h>

int main() {
    FILE *fp;
    char buf[100];
    fp = fopen("file.txt", "r"); /* opened a file for reading */
    if (fp == NULL) {
       printf("\nError : Can't open file ... ");
    }
    else { /* file is opened successfully */
       while (fgets(buf, 100, fp) != NULL) { /* read the file line by line */
          printf("%s", buf) ;
       }
    }
    fclose(fp); /* close the file */
    return 0;
}
Run this program in your system to read from a file  

In the first program, a file " file.txt " is created and some data is written into it. The file is created in the same directory in which the program file is saved.
In the second program, we read the file line by line using and then print each line on the console. We can also read a file character-by-character instead of line-by-line and write a stream to file one chracter at a time. We illustrate this using the next program which copies one file into another.

/*
 * File copy program
 */
#include <stdio.h>

int main() {
    FILE *fp1, *fp2;
    char ch;
    fp1 = fopen("file.txt", "r"); /* opened a file for reading */
    if (fp1 == NULL) {
       printf("\nError : Can't open file for reading ... ");
       return 0;
    }
    fp2 = fopen("new_file.txt", "w"); /* opened a file for reading */
    if (fp1 == NULL) {
       fclose(fp1); /* close the file opened for reading */
       printf("\nError : Can't open file for writing ... ");
       return 0;
    }
    /* both the source and target file opened successfully 
       now start copy operation */
    while(1) {
       ch = fgetc(fp1); /* read the file one character at a time */
       if(ch == EOF) { /* check if end-of-file is reached */
          break ;
       }
       else {
          fputc(ch, fp2) ; /* write the character to the file */
       }
    }
    fclose(fp1);
    fclose(fp2);
    return 0;
}
Run this program in your system to perform read-write operations on file  


Read / Write data to a file using structures
Suppose we want to store employee informations in a file. The information of each employee is a record which consists of name, grade and salary. Each record is structure. We can use fprintf and fscanf to write employee records and read them back. Following program illustrates writing and reading of structures to and from a file.

/*
 * Program to write employee informations to a file and read them back 
 */
#include <stdio.h>

/* structure to hold employee information */
typedef struct employee {
    char name[30];
    int grade;
    float salary;
}emp;

int main() {
    FILE *fp;
    char ch;
    emp e;
    fp = fopen("emp_info.txt", "w"); /* open file in write mode */
    if (fp == NULL) {
       printf("Error opening file ...");
       return 0;
    }
    do {
       printf("Employee Name : ");
       scanf("%s", &e.name);
       printf("Enter Grade : ");
       scanf("%d", &e.grade);
       printf("Enter Salary : ");
       scanf("%f", &e.salary);
       fprintf(fp, "%s %d %f\n", e.name, e.grade, e.salary) ; /* file write */
       printf ( "Do you want to add another record (Y/y) " ) ;
       fflush(stdin);
       scanf("%c", &ch);
    } while(ch == 'y' || ch == 'Y');

    fclose(fp); /* close the file after writing */
    printf("\nEmployee information saved in the file ... ");
    printf("\nLet's read those information ...\n");

    fp = fopen("emp_info.txt", "r"); /* open file in write mode */
    if (fp == NULL) {
       printf("Error opening file ...");
       return 0;
    }
    /* read the file one record at a time */
    while (fscanf(fp, "%s %d %f", e.name, &e.grade, &e.salary) != EOF) {
       printf("\nName: %s\nGrade: %d\nSalary: %f\n", e.name, e.grade, e.salary);
    }
    fclose(fp); /* close the file after reading */
    return 0;
}
Run this program in your system to take input from console and perform file operations  

We have used fflush function in the above program because after entering a employee record, we hit enter key. So an extra ' \n ' is stored in the input buffer which is not ignored by scanf function. Now when we are suppose to enter our choice ( y/Y ), scanf will read the ' \n ' character and the loop will terminate without letting user to add another employee's record.
If we need to store records in the binary format, then we must use fwrite function to write the record to a file and fread to read information back from the file. Following program illustrates the use of fwrite and fread functions.

/*
 * Program to write employee informations to a file and read them back 
 */
#include <stdio.h>

/* structure to hold employee information */
typedef struct employee {
    char name[30];
    int grade;
    float salary;
}emp;

int main() {
    FILE *fp;
    char ch;
    emp e;
    fp = fopen("emp_info.txt", "wb"); /* open file in write mode */
    if (fp == NULL) {
       printf("Error opening file ...");
       return 0;
    }
    do {
       printf("Employee Name : ");
       scanf("%s", &e.name);
       printf("Enter Grade : ");
       scanf("%d", &e.grade);
       printf("Enter Salary : ");
       scanf("%f", &e.salary);
       fwrite(&e, sizeof(e), 1, fp) ;/* write to file */
       printf ( "Do you want to add another record (Y/y) " ) ;
       fflush(stdin);
       scanf("%c", &ch);
    } while(ch == 'y' || ch == 'Y');

    fclose(fp); /* close the file after writing */
    printf("\nEmployee information saved in the file ... ");
    printf("\nLet's read those information ...\n");

    fp = fopen("emp_info.txt", "rb"); /* open file in write mode */
    if (fp == NULL) {
       printf("Error opening file ...");
       return 0;
    }
    /* read the file one record at a time */
    while (fread(&e, sizeof(e), 1, fp) == 1) {
       printf("\nName: %s\nGrade: %d\nSalary: %f\n", e.name, e.grade, e.salary);
    }
    fclose(fp); /* close the file after reading */
    return 0;
}
Run this program in your system to take input from console and perform file operations  

Please note that fwrite and fread are used to write and read memory blocks. We have demonstrated using structures. However, they can be used to write and read arrays also.

Manipulation of file pointer
In order to read from or write to any position in a file, we need to set the file pointer to point to that particular position. the fseek( ) function lets us move the file pointer to the desired location in the file. We can know the current position of the pointer using ftell( ) function.
The function fseek( fp, n, ref_pos ) takes three arguments :
fp is the file pointer, n denotes the number of bytes to move and ref_pos denotes the reference position relative to which the pointer moves. ref_pos can take one of the three constants : SEEK_SET moves the file pointer n bytes from the beginning of the file, SEEK_END moves the file pointer n bytes from the end of the file and SEEK_CUR moves the file pointer n bytes from the current position.
There is one more function called rewind( ) which places the file pointer to the beginning of the file irrespective of its current position. Following program illustrates random access of file using file pointer manipulation :

#include <stdio.h>

int main() {
   FILE *fp;
   char buf[100];
   int pos;

   /* open a file in read/write mode */
   fp = fopen("random.txt", "w+");
   printf("\nWriting to a file ... \n");
   fputs("This is a line\n", fp); /* write a line to a file */
   fputs("This is another line\n", fp); /* write another file */
   pos = ftell(fp); /* get the current position of file pointer */
   printf("Current position of put pointer : %d\n", pos);
   /* move the pointer 10 bytes backward from current position */
   fseek(fp, -10, SEEK_CUR);
   fputs("\nWriting at a random location  ", fp);
   /* move the pointer 7 bytes forward from beginning of the file */
   fseek(fp, 7, SEEK_SET);
   fputs(" Hello World  ", fp);
   fclose(fp); /* file write complete */
   printf("Writing Complete ... \n");

   /* open a file in read mode */
   fp = fopen("random.txt", "r");
   printf("\nReading from the file ... \n");
   rewind(fp); /* move the get pointer to the beginning of the file */
   /* read all contents till the end of file */
   while (fgets(buf, 100, fp) != NULL) { /* read the file line by line */
          printf("%s", buf) ;
   }
   pos = ftell(fp);
   printf("\nCurrent Position of get pointer : %d\n", pos);
   return 0;
}
Run this program in your system to perform file operations  

Back | Next