File I/O in C
In the previous chapter, we discussed standard input and output devices in C language processing. This chapter will introduce how C programmers can create, open, and close text files or binary files.
A file, whether it is a text file or a binary file, represents a series of bytes. C language not only provides top-level functions but also offers low-level (OS) calls to handle files on storage devices. This chapter will cover important file management calls.
Opening a File
You can use the fopen( ) function to create a new file or open an existing file. This call initializes an object of type FILE, which contains all the necessary information to control the stream. Below is the prototype of this function call:
FILE *fopen( const char *filename, const char *mode );
Here, filename is a string that names the file, and the access mode mode can be one of the following values:
Mode | Description |
---|---|
r | Opens an existing text file for reading. |
w | Opens a text file for writing. If the file does not exist, a new file is created. Here, your program will write content from the beginning of the file. If the file exists, it will be truncated to zero length and rewritten. |
a | Opens a text file for writing in append mode. If the file does not exist, a new file is created. Here, your program will append content to the existing file content. |
r+ | Opens a text file for both reading and writing. |
w+ | Opens a text file for both reading and writing. If the file exists, it will be truncated to zero length; if it does not exist, a new file is created. |
a+ | Opens a text file for both reading and writing. If the file does not exist, a new file is created. Reading starts from the beginning of the file, and writing can only be in append mode. |
If you are dealing with binary files, you need to use the following access modes instead of the ones above:
"rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"
Closing a File
To close a file, use the fclose( ) function. The prototype of the function is as follows:
int fclose( FILE *fp );
The fclose( ) function returns zero if the file is successfully closed, and EOF if an error occurs while closing the file. This function actually flushes the data in the buffer, closes the file, and frees all memory used for the file. EOF is a constant defined in the stdio.h header file.
The C standard library provides various functions to read and write files character by character or in fixed-length strings.
Writing to a File
Below is the simplest function to write a character to a stream:
int fputc( int c, FILE *fp );
The fputc() function writes the character value of the parameter c to the output stream pointed to by fp. If successful, it returns the written character; if an error occurs, it returns EOF. You can use the following function to write a null-terminated string to a stream:
int fputs( const char *s, FILE *fp );
The fputs() function writes the string s to the output stream pointed to by fp. If successful, it returns a non-negative value; if an error occurs, it returns EOF. You can also use the int fprintf(FILE *fp, const char *format, ...) function to write a string to a file. Try the following example:
Note: Ensure you have a tmp directory available. If it does not exist, you need to create it on your computer.
/tmp
is typically a temporary directory on Linux systems. If you are running this on a Windows system, you need to modify it to a directory that exists in your local environment, such as C:\tmp
, D:\tmp
, etc.
Example
#include <stdio.h>
int main()
{
FILE *fp = NULL;
fp = fopen("/tmp/test.txt", "w+");
fprintf(fp, "This is testing for fprintf...\n");
fputs("This is testing for fputs...\n", fp);
fclose(fp);
}
When the above code is compiled and executed, it creates a new file test.txt in the /tmp
directory and writes two lines using two different functions. Next, let's read this file.
Reading a File
Below is the simplest function to read a single character from a file:
int fgetc( FILE *fp );
The fgetc() function reads a character from the input file pointed to by fp. It returns the character read, or EOF if an error occurs. The following function allows you to read a string from a stream:
char *fgets( char *buf, int n, FILE *fp );
The fgets() function reads n - 1 characters from the input stream pointed to by fp. It copies the read string into the buffer buf, appending a null character to terminate the string.
If this function encounters a newline character '\n' or the end of the file EOF before reaching the last character, it will return the characters read, including the newline character. You can also use the int fscanf(FILE *fp, const char *format, ...) function to read a string from a file, but it stops reading at the first space or newline character.
Example
#include <stdio.h>
int main()
{
FILE *fp = NULL;
char buff[255];
fp = fopen("/tmp/test.txt", "r");
fscanf(fp, "%s", buff);
printf("1: %s\n", buff );
fgets(buff, 255, (FILE*)fp);
printf("2: %s\n", buff );
fgets(buff, 255, (FILE*)fp);
printf("3: %s\n", buff );
fclose(fp);
}
When the above code is compiled and executed, it reads the file created in the previous part, producing the following result:
1: This
2: is testing for fprintf...
3: This is testing for fputs...
First, the fscanf() method reads This because it encounters a space afterward. Then, the fgets() call reads the remaining part until the end of the line. Finally, the fgets() call reads the entire second line.
Binary I/O Functions
The following two functions are used for binary input and output:
size_t fread(void *ptr, size_t size_of_elements,
size_t number_of_elements, FILE *a_file);
size_t fwrite(const void *ptr, size_t size_of_elements,
size_t number_of_elements, FILE *a_file);
These functions are used for reading and writing blocks of data, typically arrays or structures.