Skip to main content

C File Handling

File handling is a critical aspect of programming that allows you to store and retrieve data permanently. In C, file operations enable your programs to interact with external files, making it possible to save program output, read input data, or maintain persistent information between program executions.

Understanding File Operations in C

File handling in C revolves around three main operations:

  • Creating new files
  • Opening existing files to read or modify their contents
  • Closing files when operations are complete

The C standard library provides functions and data types in the <stdio.h> header file to manage these operations efficiently.

The FILE Structure

When working with files in C, you use a pointer to a FILE structure, which serves as a handle to the file:

c
FILE *filePointer;

The FILE structure contains information about the file being accessed, including:

  • The file's current position
  • Error indicators
  • End-of-file status
  • Buffering information

Opening Files

To open a file, use the fopen() function:

c
FILE *fopen(const char *filename, const char *mode);

The function takes two parameters:

  • filename: The name of the file to open (including path if needed)
  • mode: A string specifying how you want to access the file

File Opening Modes

ModeDescription
"r"Open a file for reading (file must exist)
"w"Create a new file for writing (overwrites if file exists)
"a"Append to a file (creates file if it doesn't exist)
"r+"Open a file for both reading and writing (file must exist)
"w+"Create a file for both reading and writing (overwrites if file exists)
"a+"Open a file for reading and appending (creates file if it doesn't exist)

Adding b to any mode (e.g., "rb", "wb") specifies binary mode, which is important for non-text files.

Example: Opening a File

c
#include <stdio.h>

int main() {
FILE *filePtr;

filePtr = fopen("example.txt", "w");

if (filePtr == NULL) {
printf("Error opening the file!\n");
return 1;
}

printf("File opened successfully.\n");

// File operations would go here

return 0;
}

Closing Files

Always close files when you're done working with them using the fclose() function:

c
int fclose(FILE *filePtr);

The function returns 0 on success and EOF on failure.

c
fclose(filePtr);

Reading from Files

C provides several functions to read data from files:

1. Character Input: fgetc()

Reads a single character from a file:

c
int fgetc(FILE *filePtr);

Returns the character read as an int, or EOF if end-of-file is reached.

c
char ch;
while ((ch = fgetc(filePtr)) != EOF) {
printf("%c", ch);
}

2. String Input: fgets()

Reads a line from a file:

c
char *fgets(char *str, int n, FILE *filePtr);

Reads up to n-1 characters or until a newline character is encountered:

c
char buffer[100];
while (fgets(buffer, 100, filePtr) != NULL) {
printf("%s", buffer);
}

3. Formatted Input: fscanf()

Reads formatted data from a file:

c
int fscanf(FILE *filePtr, const char *format, ...);

Works like scanf() but reads from a file:

c
int num;
char str[50];
fscanf(filePtr, "%d %s", &num, str);

Writing to Files

C provides several functions to write data to files:

1. Character Output: fputc()

Writes a single character to a file:

c
int fputc(int ch, FILE *filePtr);
c
fputc('A', filePtr);  // Writes 'A' to the file

2. String Output: fputs()

Writes a string to a file:

c
int fputs(const char *str, FILE *filePtr);
c
fputs("Hello, World!\n", filePtr);

3. Formatted Output: fprintf()

Writes formatted data to a file:

c
int fprintf(FILE *filePtr, const char *format, ...);

Works like printf() but writes to a file:

c
int age = 25;
fprintf(filePtr, "My name is %s and I am %d years old.\n", "John", age);

File Positioning

To move to specific positions within a file:

1. fseek()

c
int fseek(FILE *filePtr, long offset, int origin);

Moves the file position indicator to a specific location:

  • offset: Number of bytes to offset from origin
  • origin: Position to use as reference point:
    • SEEK_SET: Beginning of file
    • SEEK_CUR: Current position
    • SEEK_END: End of file
c
// Move to the 10th byte from the beginning
fseek(filePtr, 10, SEEK_SET);

// Move 5 bytes forward from current position
fseek(filePtr, 5, SEEK_CUR);

// Move 3 bytes backward from the end
fseek(filePtr, -3, SEEK_END);

2. ftell()

Returns the current file position:

c
long ftell(FILE *filePtr);
c
long position = ftell(filePtr);
printf("Current position: %ld\n", position);

3. rewind()

Sets the file position indicator to the beginning of the file:

c
void rewind(FILE *filePtr);

Binary File Operations

For working with binary files, use fread() and fwrite():

fread()

c
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *filePtr);

Reads data from a binary file:

  • ptr: Pointer to the block of memory to store data
  • size: Size of each element in bytes
  • nmemb: Number of elements to read
  • filePtr: File pointer

fwrite()

c
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *filePtr);

Writes data to a binary file with the same parameters as fread().

Complete Example: Text File Operations

c
#include <stdio.h>

int main() {
FILE *filePtr;
char buffer[100];

// Writing to a file
filePtr = fopen("myfile.txt", "w");
if (filePtr == NULL) {
printf("Error opening file for writing!\n");
return 1;
}

fprintf(filePtr, "Learning C File Handling\n");
fprintf(filePtr, "Line 2: More text here\n");
fprintf(filePtr, "Line 3: Final line of the file\n");

fclose(filePtr);

// Reading from a file
filePtr = fopen("myfile.txt", "r");
if (filePtr == NULL) {
printf("Error opening file for reading!\n");
return 1;
}

printf("File contents:\n");
while (fgets(buffer, sizeof(buffer), filePtr) != NULL) {
printf("%s", buffer);
}

fclose(filePtr);
return 0;
}

Complete Example: Binary File Operations

c
#include <stdio.h>
#include <string.h>

struct Student {
char name[50];
int age;
float gpa;
};

int main() {
FILE *filePtr;
struct Student students[3] = {
{"Alice", 20, 3.8},
{"Bob", 22, 3.5},
{"Charlie", 21, 3.9}
};
struct Student readStudents[3];

// Writing structures to a binary file
filePtr = fopen("students.bin", "wb");
if (filePtr == NULL) {
printf("Error opening binary file for writing!\n");
return 1;
}

fwrite(students, sizeof(struct Student), 3, filePtr);
fclose(filePtr);

// Reading structures from the binary file
filePtr = fopen("students.bin", "rb");
if (filePtr == NULL) {
printf("Error opening binary file for reading!\n");
return 1;
}

fread(readStudents, sizeof(struct Student), 3, filePtr);

// Display the read data
printf("Student Records:\n");
for (int i = 0; i < 3; i++) {
printf("Name: %s, Age: %d, GPA: %.1f\n",
readStudents[i].name,
readStudents[i].age,
readStudents[i].gpa);
}

fclose(filePtr);
return 0;
}

Error Handling in File Operations

Always check the return value of file operations to handle errors gracefully:

c
if (filePtr == NULL) {
perror("File operation failed");
// Handle the error
}

The perror() function displays a descriptive error message based on the value of errno.

Best Practices for File Handling

  1. Always close files when you're done with them to free up system resources.
  2. Check for errors after file operations.
  3. Use binary mode ("b") when working with non-text files.
  4. Flush the buffer with fflush() when necessary to ensure data is written immediately.
  5. Use appropriate file access modes based on your needs.
  6. Handle file paths correctly, considering relative vs. absolute paths.

Summary

File handling in C allows your programs to interact with external files, providing persistent storage. The key functions to remember are:

  • fopen() for opening files
  • fclose() for closing files
  • fgetc(), fgets(), and fscanf() for reading
  • fputc(), fputs(), and fprintf() for writing
  • fseek(), ftell(), and rewind() for file positioning
  • fread() and fwrite() for binary file operations

With these tools, you can create, read, update, and manage files effectively in your C programs.



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)