How to Write and Read Data from File in C

Get Certified in C Programming for Free and Take Your Skills to the Next Level

File Handling in C

File handling is an essential concept in C programming. It allows preserving data even after the program execution is over. This makes it simple to efficiently store and access vast volumes of data. File handling gives C programs a lot of power and flexibility.

Why Files are Needed

Using files instead of variables has many advantages:

  • Files allow storing persistent data that can be accessed later. Variable values are lost when the program terminates.
  • Files provide efficient access to large amounts of data. It is tedious to declare hundreds of variables.
  • Data in files can be easily shared between programs. Just read the common file.
  • Files allow easy data backup and transfer between systems. Just copy or move the file.

Overall, using files instead of variables to store data saves time and effort when working with large data sets.

Types of Files in C

In C, there are primarily two sorts of files:

1. Text Files

Text files contain data in ASCII text form. They have extensions like .txt, .c, .cpp, etc.

Key features:

  • Using a text editor is simple to develop and modify.
  • Human-readable.
  • Requires less storage space compared to binary files.
  • Not very secure as the contents are visible.

2. Binary Files

Binary files contain data in binary form (1s and 0s). They have extensions like .docx, .jpeg, .exe, etc.

Key features:

  • Store data more compactly than text files.
  • Provide better security as the contents are not directly visible.
  • Capable of storing large data like multimedia.
  • Require specific programs to read and modify.

File Operations in C

Let’s look at the common file operations in C:

1. Creating a New File

Technology is evolving rapidly!
Stay updated with DataFlair on WhatsApp!!

The fopen() function can be used to create a new file.

FILE *fp;
fp = fopen("data.txt","w"); //create data.txt file in write mode

The first parameter is the filename, and the second parameter is the mode “w” for write.

2. Opening an Existing File

To open an existing file, specify the filename and appropriate mode while calling fopen():

FILE *fp;

//open text.txt in read mode
fp = fopen("text.txt","r");

//open image.jpeg in binary write mode 
fp = fopen("image.jpeg","wb");

3. Closing a File

Always close opened files using fclose(fp) when done. This frees up resources and prevents data corruption:

fclose(fp); //close file pointed by fp

4. Writing to a File

1. Writing to a Text File

To write to a text file, we can use functions like fprintf(), fputc(), etc.

Example:

#include <stdio.h>

int main() {

  FILE *fpointer = fopen("data.txt","w");
  
  fprintf(fpointer, "This is some text\n");
  fprintf(fpointer, "Written to a file\n");
  
  fclose(fpointer);
  
  return 0;
}

This writes the given text to data.txt.

We can also write individual characters using fputc():

fputc('A', fpointer); //writes character 'A' to file

Always check the return value from writing functions to catch errors:

if(fprintf(fpointer, text) < 0) {
   //error occurred
   printf("Unable to write to file");
}

2. Writing to a Binary File

For binary files, we use the fwrite() function.

Example:

#include <stdio.h>

struct Record {
  char name[30];
  int age;
  float salary;
};

int main() {

  struct Record r1 = {"John", 30, 4000};
  
  FILE *fp = fopen("data.bin","wb");
  
  fwrite(&r1, sizeof(struct Record), 1, fp);
  
  fclose(fp);

  return 0;
}

This writes the struct to the binary file data.bin.

We can write multiple structs like this in a loop.

5. Reading from a File

1. Reading from a Text File

To read from a text file, use fscanf(), fgetc() and related functions.

Example:

#include <stdio.h>

int main() {

  char str[100];
  int num;
  
  FILE *fptr = fopen("text.txt","r");
  
  if(fptr == NULL) {
    printf("Error opening file"); 
    return 1;
  }
  
  //read string from file
  fscanf(fptr,"%s", str); 
  
  //read integer
  fscanf(fptr, "%d", &num);  

  printf("String is: %s\n", str);
  printf("Integer is: %d", num);
  
  fclose(fptr);

  return 0;
}

This reads a string and integer from the text file text.txt.

We can also read individual characters using fgetc(fptr).

Always check for end of file (EOF) condition to avoid errors while reading:

while(!feof(fptr)) {
  //keep reading from file
}

2. Reading from a Binary File

#include <stdio.h>

struct Record {
  char name[30];
  int age;
  float salary;
};

int main() {

  struct Record r;
  
  FILE *fp = fopen("data.bin","rb");
  
  if(fp == NULL) {
    printf("Error opening file");
    return 1;
  }

  //read struct from file
  fread(&r, sizeof(struct Record), 1, fp);

  printf("Name: %s\n", r.name);  
  printf("Age: %d\n", r.age);
  printf("Salary: %f", r.salary);

  fclose(fp);
  
  return 0;
}

This reads the struct from binary file data.bin into r.

Opening Modes in Standard I/O

Opening ModeDescriptionIf File Does Not Exist
rOpen for reading only.Returns NULL.
rbOpen for reading only in binary mode.Returns NULL.
wOpen for writing only. Overwrites existing content.Creates new file.
wbOpen for writing only in binary mode. Overwrites existing content.Creates new file.
aOpen for appending only. Data is added to the end of file.Creates new file.
abOpen for appending only in binary mode. Data added to end of file.Creates new file.
r+Open for both reading and writing.Returns NULL.
rb+Open for both reading and writing in binary mode.Returns NULL.
w+Open for reading and writing. Overwrites existing content.Creates new file.
wb+Open for reading and writing in binary mode. Overwrites existing content.Creates new file.
a+Open for reading and appending.Creates new file.
ab+Open for reading and appending in binary mode.Creates new file.

Handling Errors and Exceptions in C

Some common file operation errors:

  • File open failure
  • File read/write failure
  • Trying to read at EOF
  • File not found
  • Access violations

Ways to handle errors:

  • Check return values from file functions like fopen(), fread() etc.
  • Use perror() to print the error message for the last error that occurred.
  • Check for EOF using feof() while reading.
  • Use descriptive error messages and clean up resources properly.

Advanced File Operations

1. Using fseek() for Positioning

The fseek() function allows moving the file position indicator to a desired location:

fseek(fptr, offset, fromwhere);

The offset is number of bytes. fromwhere can be:

  • SEEK_SET – start of file
  • SEEK_CUR – current position
  • SEEK_END – end of file

Example:

#include <stdio.h>

struct Record {
  int id;
  //other fields
};

int main() {

  struct Record r;

  FILE *fp = fopen("records.bin","rb");
  
  //move pointer to end
  fseek(fp, 0, SEEK_END); 
  
  //read last record
  fseek(fp, -sizeof(struct Record), SEEK_CUR);
  fread(&r, sizeof(struct Record), 1, fp);

  //print last record's id
  printf("Last ID: %d", r.id);
  
  fclose(fp);

  return 0;
}

This reads the last record in reverse order from a binary file.

Best Practices and Tips

Some tips for efficient file handling:

  • Always check if the file opening was successful before further operations.
  • Use relative paths instead of absolute file paths for portability.
  • Close all opened files using fclose() before program termination.
  • Use binary mode for non-textual data for performance.
  • Handle errors and exceptions properly for robustness.
  • Use fseek() and ftell() for random file access.

Conclusion

File handling allows storing persistent data for later use, leading to efficient and robust C programs. The key concepts include opening, closing, reading and writing files in different modes. By following best practices and error handling, we can build powerful applications using file handling in C.

Your opinion matters
Please write your valuable feedback about DataFlair on Google

follow dataflair on YouTube

Leave a Reply

Your email address will not be published. Required fields are marked *