C File Handling - Complete Guide
Master C file handling including file operations, file modes, file functions with detailed syntax, practical examples, and programming best practices.
File Operations
Create, Read, Write, Update
File Modes
Text & Binary Modes
File Functions
Complete Reference
Introduction to File Handling in C
File handling in C enables programs to store data permanently on disk and retrieve it when needed. It's essential for creating applications that need to persist data between program executions, such as databases, configuration files, and data logs.
Why File Handling?
- Data Persistence: Store data permanently on disk
- Large Data Handling: Process data larger than available memory
- Data Sharing: Share data between different programs
- Configuration Storage: Store program settings and preferences
- Backup & Recovery: Create backups and restore data
File Types in C
- Text Files: Human-readable, store characters
- Binary Files: Machine-readable, store raw bytes
- Sequential Files: Processed in sequence
- Random Access Files: Access any position directly
Important File Concepts
File handling involves: FILE pointer (stream pointer), Opening mode (read/write/append), File position indicator (current read/write position), and Buffer (temporary storage). Always close files after operations to prevent data loss.
File Opening Modes
File opening modes determine how a file will be accessed. Each mode has specific characteristics for text and binary files.
| Mode | Description | File Exists | File Doesn't Exist |
|---|---|---|---|
| Text File Modes | |||
|
"r"
|
Read mode. Opens file for reading. | Opens successfully | Returns NULL |
|
"w"
|
Write mode. Creates new file or truncates existing. | Truncates to zero length | Creates new file |
|
"a"
|
Append mode. Opens file for writing at end. | Opens, writes at end | Creates new file |
|
"r+"
|
Read/Write mode. Opens file for both. | Opens successfully | Returns NULL |
|
"w+"
|
Write/Read mode. Creates/truncates file. | Truncates to zero length | Creates new file |
|
"a+"
|
Append/Read mode. Opens for reading and appending. | Opens, writes at end | Creates new file |
| Binary File Modes | |||
|
"rb"
|
Binary read mode. | Opens successfully | Returns NULL |
|
"wb"
|
Binary write mode. | Truncates to zero length | Creates new file |
|
"ab"
|
Binary append mode. | Opens, writes at end | Creates new file |
|
"rb+"
|
Binary read/write mode. | Opens successfully | Returns NULL |
|
"wb+"
|
Binary write/read mode. | Truncates to zero length | Creates new file |
|
"ab+"
|
Binary append/read mode. | Opens, writes at end | Creates new file |
C File Functions Reference Table
Complete reference of all file handling functions in C with their syntax, purpose, and return values.
| Function | Syntax | Purpose | Return Value |
|---|---|---|---|
| fopen() |
FILE *fopen(const char *filename, const char *mode);
|
Opens a file and returns a FILE pointer | FILE* on success, NULL on failure |
| fclose() |
int fclose(FILE *stream);
|
Closes an opened file | 0 on success, EOF on error |
| fgetc() |
int fgetc(FILE *stream);
|
Reads a character from file | Character read or EOF |
| fputc() |
int fputc(int char, FILE *stream);
|
Writes a character to file | Character written or EOF |
| fgets() |
char *fgets(char *str, int n, FILE *stream);
|
Reads a string from file | str on success, NULL on failure |
| fputs() |
int fputs(const char *str, FILE *stream);
|
Writes a string to file | Non-negative on success, EOF on error |
| fscanf() |
int fscanf(FILE *stream, const char *format, ...);
|
Reads formatted input from file | Number of items read |
| fprintf() |
int fprintf(FILE *stream, const char *format, ...);
|
Writes formatted output to file | Number of characters written |
| fread() |
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
Reads binary data from file | Number of items read |
| fwrite() |
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
|
Writes binary data to file | Number of items written |
| fseek() |
int fseek(FILE *stream, long offset, int whence);
|
Moves file position indicator | 0 on success, non-zero on error |
| ftell() |
long ftell(FILE *stream);
|
Returns current file position | Current position or -1L on error |
| rewind() |
void rewind(FILE *stream);
|
Sets file position to beginning | None (void) |
| feof() |
int feof(FILE *stream);
|
Checks end-of-file indicator | Non-zero if EOF, 0 otherwise |
| ferror() |
int ferror(FILE *stream);
|
Checks error indicator | Non-zero if error, 0 otherwise |
| clearerr() |
void clearerr(FILE *stream);
|
Clears error and EOF indicators | None (void) |
| remove() |
int remove(const char *filename);
|
Deletes a file | 0 on success, non-zero on error |
| rename() |
int rename(const char *oldname, const char *newname);
|
Renames a file | 0 on success, non-zero on error |
fopen() for NULL before proceeding.
Always close files with fclose() after operations to free resources and ensure data is written to disk.
Text File Operations
Text files store data in human-readable format. Each line ends with a newline character ('\n').
#include <stdio.h>
int main(void) {
FILE *fp = fopen("demo.txt", "w");
if (!fp) return 1;
fprintf(fp, "Hello\nLine 2\n");
fclose(fp);
fp = fopen("demo.txt", "r");
char line[80];
while (fgets(line, sizeof line, fp))
printf("%s", line);
fclose(fp);
return 0;
}
Hello
Line 2
Binary File Operations
Binary files store data in machine-readable format (raw bytes). They're more efficient for storing structured data like arrays and structures.
#include <stdio.h>
typedef struct { int id; char name[20]; } Item;
int main(void) {
Item a = {1, "Ada"};
Item b;
FILE *fp = fopen("data.bin", "wb");
fwrite(&a, sizeof a, 1, fp);
fclose(fp);
fp = fopen("data.bin", "rb");
fread(&b, sizeof b, 1, fp);
fclose(fp);
printf("%d %s\n", b.id, b.name);
return 0;
}
File Error Handling
Proper error handling is crucial for robust file operations. Always check function return values and use error handling functions.
#include <stdio.h>
int main(void) {
FILE *fp = fopen("missing.txt", "r");
if (fp == NULL) {
perror("fopen failed");
return 1;
}
fclose(fp);
return 0;
}
Best Practices for File Handling
File Handling Best Practices:
- Always check fopen() return value: Never assume file opened successfully
- Close files properly: Always call fclose() to free resources and flush buffers
- Use appropriate file modes: Choose the right mode for your operation
- Check for EOF properly: Use feof() after read operations fail
- Handle errors gracefully: Provide meaningful error messages
- Use binary mode for structured data: Use "b" mode for arrays and structures
- Check write operations: Verify that write operations succeeded
- Use buffered I/O wisely: Large buffers for large files, small for small files
- Validate file names: Check for invalid characters in file names
- Clean up temporary files: Remove temporary files when done
- Not checking if fopen() returned NULL
- Forgetting to close files (resource leak)
- Using text mode for binary data (corruption)
- Not handling partial read/write operations
- Assuming file position after operations
- Not clearing error indicators before reuse
- Using gets() instead of fgets() for safety
Key Takeaways
- File handling allows persistent data storage in C programs
- Always use FILE pointers to work with files
- Check fopen() return value for NULL before proceeding
- Text files store human-readable data, binary files store raw bytes
- Choose appropriate file modes (r, w, a, +, b combinations)
- Use fclose() to close files and free resources
- fread()/fwrite() for binary data, fprintf()/fscanf() for formatted text
- Use fseek(), ftell(), rewind() for random file access
- Implement error handling with feof(), ferror(), clearerr()
- Follow best practices for robust and secure file operations