Basics of File Handling in C
Programs can permanently save data on secondary storage devices, such as discs, with C’s file handling capabilities. This is important because information that is only kept in variables in the primary memory (RAM) is transient and disappears when the application terminates or the power is switched off. Large data processing and long-term data retention are made possible by files.
File and I/O management statements are not built into C. All file I/O uses Standard C Library function calls. The header file provides function declarations, definitions, structures, and macros. First, include in any application that handles files.
The FILE Pointer
In order to work with a file in C, your program must have a means of referencing it. In , the standard library introduces a unique structural type named FILE. The system establishes a temporary buffer space to move data between memory and the disc when you open a file. A FILE structure is used to manage this buffer as well as additional file information, such as the file’s position, mode, and status.
A pointer is how you work with this FILE structure. This is how you declare a reference to a file:
FILE *file_pointer_variable;
For instance, FILE *in_file; or FILE *fp;. Your software needs a different FILE pointer for every open file it works with.
Basic File Operations
You can do the following basic operations on a file:
- Launching a document.
- Retrieving information from the file.
- Adding information to the file.
- The file is being closed. Among the other operations are seeking, generating, and naming.
How basic operations work using the standard C library functions
Using the standard C library functions, these fundamental operations operate as follows:
- Opening a File (fopen): Using fopen to open a file A file must be opened before it can be read from or written to. For this, the fopen() function is employed. The filename and the access mode are the two string arguments that fopen() accepts. A pointer to the FILE structure linked to the opened file is returned if the attempt to open the file in the designated mode is successful. It returns NULL if the file cannot be opened (for example, file not found for reading, permission difficulties).
- Common Access Modes
- “r” stands for read mode. allows you to read the file. There must be a file. At the start, the file position is established.
- “w” stands for write mode. allows you to write to the file. The file is generated if it doesn’t already exist. The contents of the file are abruptly truncated, if it exists at all. At the start, the file position is established.
- “a”: Mode of appending. adds fresh data to the end of the file while opening it for writing. The file is generated if it doesn’t already exist. Its contents are maintained if it exists. At the conclusion, the file position is set.
- Verifying the return value of fopen() is crucial for confirming that the file was successfully opened. The returned pointer can be compared to NULL.
- Carrying out input/output After the file has been successfully opened, you can read and write using a variety of standard library functions. The following are a few fundamental character and formatted I/O functions:
- fgetc(FILE *fp): Reads the following single character from the file that fp has pointed to. If an error occurs or the file’s end is reached, it returns EOF or the character read (as an int). The macro EOF is defined in and is usually set to -1.
- fputc(int c, FILE *fp): Adds the single character c to the file that fp is pointing to. When an error occurs, it returns either the written character (as an int) or EOF.
- fgets(char *buffer, int size, FILE *fp): Reads characters into the character array buffer from the file that fp points to. It reads until a newline character (\n) is read, until the end of the file is reached, or until size – 1 characters are reached, whichever happens first. If the newline character is read, it is saved in the buffer. If successful, it returns buffer; if unsuccessful, or if the file ends before any characters are read, it returns NULL.
- fputs(const char *str, FILE *fp): The null-terminated string str is written to the file that fp points to. A newline character is not automatically written.
- fprintf(FILE *fp, const char *format, …): Formatted output is written to the file that fp points to. Similar to printf(), but instead of sending the output to standard output (stdout), this sends it to a specified file. Format specifiers like %d, %s, and %f are used.
- fscanf(FILE *fp, const char *format, …): Reads input that has been prepared from the file that fp points to. Similar to scanf(), but instead of reading from standard input (stdin), this reads from a specified file. If the file is finished before any items are matched, it returns EOF. Otherwise, it returns the number of input items that were successfully matched and assigned.
- Closing a File (fclose) The fclose() method should be used to close a file when you have completed working with it. The FILE pointer is a parameter passed to fclose(). When a file is closed, the operating system resources linked to it are released and any data that is still in the temporary buffer is written to the disc.
Example 1: Using fprintf to write to a text file
#include <stdio.h> // For file I/O functions like fopen, fprintf, fclose, FILE, NULL, EOF
#include <stdlib.h> // For exit()
int main() {
FILE *output_file = NULL; // Declare a FILE pointer, initialize to NULL
const char *filename = "output.txt";
const char *mode = "w"; // Write mode: creates file or truncates if exists
printf("Attempting to open file \"%s\" in mode \"%s\"...\n", filename, mode);
// Open the file in write mode
output_file = fopen(filename, mode);
// Check if the file was opened successfully
if (output_file == NULL) { // fopen returns NULL on failure
// Use perror for system error message or fprintf to stderr
perror("Error opening output file"); // Good for showing OS error details
// Alternatively: fprintf(stderr, "Could not open file %s\n", filename);
return EXIT_FAILURE; // Use EXIT_FAILURE from <stdlib.h>
}
printf("File \"%s\" opened successfully.\n", filename);
// Write formatted data to the file
fprintf(output_file, "This is the first line.\n");
fprintf(output_file, "Writing an integer: %d\n", 123);
fprintf(output_file, "Writing a double: %.2f\n", 45.67);
fprintf(output_file, "End of the file.\n");
printf("Data written to the file.\n");
// Close the file
fclose(output_file);
printf("File \"%s\" closed.\n", filename);
return 0; // Indicate successful execution
}
Output
Attempting to open file "output.txt" in mode "w"...
File "output.txt" opened successfully.
Data written to the file.
File "output.txt" closed.
Example 2: Using fgetc to read from a text file
The basic cycle of file handling is demonstrated by these examples: define a FILE pointer, open the file, check for errors, execute I/O operations, then shut the file.
#include <stdio.h> // For file I/O functions like fopen, fgetc, fclose, FILE, NULL, EOF
#include <stdlib.h> // For exit()
int main() {
FILE *input_file = NULL; // Declare a FILE pointer, initialize to NULL
int c; // Use int to properly handle EOF
const char *filename = "output.txt";
const char *mode = "r"; // Read mode: file must exist
printf("Attempting to open file \"%s\" in mode \"%s\"...\n", filename, mode);
// Open the file in read mode
input_file = fopen(filename, mode);
// Check for errors
if (input_file == NULL) {
perror("Error opening input file");
return EXIT_FAILURE;
}
printf("File \"%s\" opened successfully. Reading contents:\n", filename);
// Read characters one by one until EOF is reached
// fgetc returns EOF at the end of the file or on error
while ((c = fgetc(input_file)) != EOF) {
// Print the character read
putchar(c); // putchar is often more efficient for single characters than printf
// Alternatively: printf("%c", c);
}
// After the loop, c is EOF (or an error value)
// You could use feof() or ferror() to check if it was truly EOF or an error
if (ferror(input_file)) {
perror("Error reading from file");
// Handle the read error
} else if (feof(input_file)) {
// Reached end of file successfully
printf("\nReached end of file.\n");
}
// Close the file
fclose(input_file);
printf("File \"%s\" closed.\n", filename);
return 0; // Indicate successful execution
}
Output
This is the first line.
Writing an integer: 123
Writing a double: 45.67
End of the file.
Attempting to open file "output.txt" in mode "w"...
File "output.txt" opened successfully.
Data written to the file.
File "output.txt" closed.
The relationship between these functions and the common console I/O functions we covered before is evident. For example, fprintf is similar to printf, fscanf to scanf, fgetc to getchar, and fputc to putchar. The addition of the FILE pointer argument to indicate which file to work on is the primary distinction.
A programming exercise that uses sizeof to determine the sizes of data types, which are subsequently written to a file using file I/O routines. This exercise relates to our earlier discussion of the sizeof operator. This demonstrates how, when reading or writing structured data to files, sizeof and file management are frequently combined to work with data sizes portably.
You can also read What Is C Dynamic Memory Allocation With Code Example?