Learn C Programming
File Handling
File handling in C is a fundamental aspect of programming that allows us to interact with files on a computerโs storage system. In the C programming language, file handling is achieved through standard library functions defined in <stdio.h>
The following operations can be performed on a file:-
- Creating a new file
- Opening an existing file
- Reading data from an existing file
- Writing data to a file
- Moving data to a specific location on the file
- Closing the file
Why Do We Need File Handling in C?
There are times when, despite compiling and running a program, the output generated does not serve our intended purpose. In such cases, we might want to check the programโs output various times. Now, compiling and running the very same program multiple times becomes a tedious task for any programmer. It is exactly where file handling becomes useful. Let us look at a few reasons why file handling makes programming easier for all:
- Reusability:ย File handling allows us to preserve the information/data generated after we run the program.
- Saves Time:ย Some programs might require a large amount of input from their users. In such cases, file handling allows you to easily access a part of a code using individual commands.
- Commendable storage capacity: When storing data in files, however, you can leave behind the worry of storing all the info in bulk in any program.
- Portability:ย Weย can transfer the contents available in any file to another one in the computer system without any data loss.ย This saves a lot of effort and minimises the risk of flawed coding.
Types of Files in a C Program
When referring to file handling, we refer to files in the form of data files. Now, these data files are available in 2 distinct forms in the C language, namely:
- Text Files
- Binary Files
- Random Access file
Text Files
A text file contains data in theย form of ASCII charactersย and is generally used to store a stream of characters.
- Each line in a text file ends with a new line character (โ\nโ).
- Any text editor can read or write it.
- Generally, they store these files with a .txt file extension.
- Text files can also store the source code.
Binary Files
A binary file contains data inย binary form (i.e. 0โs and 1โs)ย instead of ASCII characters. They contain data that is stored in a similar manner to how it is stored in the main memory.
- The binary files can be created only from within a program and their contents can only be read by a program.
- More secure as they are not easily readable.
- They are generally stored withย .binย file extension.
Random Access file
Random file access means that you can take the file pointer to any part of the file for reading or writing. There is no need to read each record sequentially, if we want to access a particular record. C supports these functions for random access file processing:-ย fseek(), ftell(), rewind().
Functions For File Handling
We can use a variety of functions in order to open a file, read it, write more data, create a new file, close or delete a file, search for a file, etc. These are known as file handling operators in C. Hereโs a list of functions that allow you to do so:
Function | Description |
---|---|
ย ย fopen() | Creates a new file and Opens and existing file for use. |
ย ย fclose() | Closes a file which has been opened for use. |
ย ย fgetc() | Reads a character from a file. |
ย ย fputc() | Writes a character to a file. |
ย ย fprintf() | Writes a set of data values to a file. |
ย ย fscanf() | Reads a set of data values from a file. |
ย ย fgetw() | Reads an integer from a file. |
ย ย fputw() | Writes an integer to a file. |
ย ย fseek() | Sets the position to a desired point in the file. |
ย ย ftell() | Gives the current position in the file. |
ย ย rewind() | Sets the position to the beginning of the file.. |
Note: Firstly, it is important to know that we must declare a file-type pointer when we are working with various files in a program. This helps establish direct communication between a program and the files. Here is how you can do it: FILE *fpointer; Out of all the operations/functions mentioned above, let us discuss some of the basic operations that we perform in the C language.
Hereโs an overview of the basic file handling functions in C:
fopen()
: Thefopen()
function is used to open a file. It takes two arguments: the file path and the mode. The mode specifies whether the file will open for reading, writing, or both. The function returns a pointer to aFILE
structure that represents the opened file.
FILE* fopen(const char* filename, const char* mode);
fclose()
: Thefclose()
function is used to close a file that was previously opened withfopen()
. It takes a pointer to aFILE
structure as an argument.
int fclose(FILE* stream);
fputc()
,fgetc()
,fputs()
, andfgets()
: These functions are used for reading and writing individual characters or strings to and from files.
int fputc(int character, FILE* stream);
int fgetc(FILE* stream);
int fputs(const char* str, FILE* stream);
char* fgets(char* str, int num, FILE* stream);
fwrite()
andfread()
: These functions are used for reading and writing blocks of data to and from files.
size_t fwrite(const void* ptr, size_t size,
size_t count, FILE* stream);
size_t fread(void* ptr, size_t size, size_t count, FILE* stream);
feof()
: Thefeof()
function checks if the end of the file has been reached.
int feof(FILE* stream);
fseek()
andftell()
: These functions are used for file positioning.
int fseek(FILE* stream, long offset, int origin);
long ftell(FILE* stream);
Let us take a look at a few more opening modes used in the C programs:
Opening Modes of C in Standard I/O of a Program | ||
Mode in Program | Meaning of Mode | When the file doesnโt exist |
r | Open a file for reading the content. | In case the file doesnโt exist in the location, then fopen() will return NULL. |
rb | Open a file for reading the content in binary mode. | In case the file doesnโt exist in the location, then fopen() will return NULL. |
w | Open a file for writing the content. | In case the file exists, its contents are overwritten. ย In case the file doesnโt exist in the location, then it will create a new file. |
wb | Open a file for writing the content in binary mode. | In case the file exists, then its contents will get overwritten. ย In case the file doesnโt exist in the location, then it will create a new file. |
a | Open a file for appending the content. | In case the file doesnโt exist in the location, then it will create a new file. |
ab | Open a file for appending the content in binary mode. | In case the file doesnโt exist in the location, then it will create a new file. |
r+ | Open a file for both writing and reading the content. | In case the file doesnโt exist in the location, then fopen() will return NULL. |
rb+ | Open a file for both writing and reading the content in binary mode. | In case the file doesnโt exist in the location, then fopen() will return NULL. |
w+ | Open a file for both writing and reading. | In case the file exists, its contents are overwritten. ย In case the file doesnโt exist in the location, then it will create a new file. |
wb+ | Open a file for both writing and reading the content in binary mode. | In case the file exists, its contents are overwritten. ย In case the file doesnโt exist in the location, then it will create a new file. |
a+ | Open a file for both appending and reading the content. | In case the file doesnโt exist in the location, then it will create a new file. |
ab+ | Open a file for both appending and reading the content in binary mode. | In case the file doesnโt exist in the location, then it will create a new file. |
As given above, if you want to perform operations on a binary file, then you have to append โbโ at the last. For example, instead of โwโ, you have to use โwbโ, instead of โa+โ you have to use โa+bโ. Always handle errors properly when working with files, and remember to close the file using fclose() after we finish with it to release system resources.
Hereโs a simple example of reading and writing to a file in C:
#include <stdio.h>
int main() {
FILE* file = fopen("example.txt", "w");
if (file != NULL) {
fputs("Hello, File Handling in C!", file);
fclose(file);
} else {
printf("Failed to open the file.\n");
return 1;
}
file = fopen("example.txt", "r");
if (file != NULL) {
char buffer[100];
fgets(buffer, sizeof(buffer), file);
printf("Content read from file: %s\n", buffer);
fclose(file);
} else {
printf("Failed to open the file.\n");
return 1;
}
return 0;
}
Random Access To Files
ftell()
ftell()ย takes a file pointer and returns a number of type long, that corresponds to the current position. This function is useful in saving the current position of a file.
n=ftell(fp)
n would give the relative offset( in bytes ) of the current position. This means that the program has already read or written n bytes. ย
rewind()
rewindย takes a file pointer and resets the position to the start of the file.
rewind(fp);
n = ftell(fp);
After using the `rewind` function, remember that it sets the file position to the start of the file. Keep in mind that you should number the first byte in the file as 0, the second as 1, and so on. ย
fseek()
The fseek function allows programmers to move the file position to a desired location within the file.
fseek(file ptr, offset, position);
For instance:
#include <stdio.h>
int main() {
FILE* filePointer = fopen("data.txt", "r");
if (filePointer == NULL) {
printf("Error opening the file.\n");
return 1;
}
fseek(filePointer, 10, SEEK_SET);
// Move the file pointer to the 10th byte from the beginning.
char buffer[100];
while (fgets(buffer, sizeof(buffer), filePointer) != NULL) {
printf("%s", buffer);
}
fclose(filePointer);
return 0;
}
The position can take one of the following those values: ย
Value | Meaning |
---|---|
0 | Beginning of file |
1 | Current position |
2 | End of file |
The offset may be positive, meaning move forward, or negative, meaning move backwards.
For Example:
Statements | Meaning |
---|---|
fseek(fp,0L,0); | Beginning of file |
fseek(fp,0L,1); | Current position |
fseek(fp,0L,2); | End of file |
fseek(fp,m,0); | Move to (m+1)th byte in the file. |
fseek(fp,m,1); | Go forward by m bytes. |
fseek(fp,-m,1); | Go forward by m bytes from the current position |
fseek(fp,-m,2); | Go backwards by m bytes from the end. |
Error Handling
Error Handling During I/O Operations
It is possible that an error occur during I/O operations on a file. Typical error situations includes:
- Trying to read beyond the end-of-file mark.
- Device overflow.
- Trying to use an unopened file.
- When storing data in files, you can confidently leave behind the worry of storing all the information in bulk within any program. Additionally, using this approach, you can better manage, access, and organize the data efficiently.
- Opening a file with an invalid filename.
- Lastly, attempting to write to a write-protected file.
Error Handling in File Operations
When dealing with file handling in C, however, it is crucial to handle errors properly to ensure robustness and prevent unexpected behavior. To check for errors during file operations, you can use the errno
variable and the perror()
function:
#include <stdio.h>
int main() {
FILE* filePointer = fopen("data.txt", "r");
if (filePointer == NULL) {
perror("Error");
return 1;
}
// File operations here...
fclose(filePointer);
return 0;
}
Furthermore, the perror()
function will print an error message describing the error that occurred during the file operation.
Divide by Zero Errors
It is a common problem that at the time of dividing any number, programmers often do not check if a divisor is zero, and finally, it creates a runtime error. ย
Program Exit Status
In this, it provides anย exit()ย function which takes two values for printing successful or unsuccessful termination by usingย EXIT_SUCCESSย andย EXIT_FAILURE. Lastly, the standard library header file โstdlib.hโ defines the exit() function.
ย