1. Core Function Interfaces
1.1 fwrite
1.1.1 Function Prototype
c
#include <stdio.h> // Required header file
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
1.1.2 Functionality
Write data from memory to the specified file stream in batches in binary form without any format conversion. It is the core function for processing binary files (e.g., structures, images, audio).
1.1.3 Parameters
| Parameter Name | Data Type | Meaning |
|---|---|---|
| ptr | const void * | Starting address of the memory where the data to be written is stored (can be the address of an array, structure, or ordinary variable) |
| size | size_t | Byte size of a single data block (e.g., sizeof(int), sizeof(Student)) |
| nmemb | size_t | Number of data blocks to be written |
| stream | FILE * | Pointer to the target file stream (must be opened in binary mode via fopen) |
1.1.4 Return Value
size_t:
- Success: Returns the number of complete data blocks actually written (equal to nmemb)
- Failure: Returns a value less than nmemb (error can be checked via ferror(stream))
Note :
Total bytes written = size * nmemb (on success)
1.2 fread --- Binary Batch Reading of File Streams
1.2.1 Function Prototype
c
#include <stdio.h> // Required header file
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
1.2.2 Function Description
Read data from the specified file stream to memory in batches in binary form and restore it to the original data type (e.g., structure, array). It is the matching reading function of fwrite.
1.2.3 Parameters
| Parameter Name | Data Type | Meaning |
|---|---|---|
| ptr | void * | Starting address of the memory to receive data (sufficient space must be allocated in advance, such as array, structure variable) |
| size | size_t | Byte size of a single data block (must be consistent with the size used during writing) |
| nmemb | size_t | Number of data blocks to be read |
| stream | FILE * | Pointer to the source file stream (must be opened in binary mode via fopen) |
1.2.4 Return Value
size_t:
- Success: Returns the number of complete data blocks actually read (≤ nmemb)
- End of file reached: Returns 0
- Failure: Returns a value less than nmemb (ferror(stream)/feof(stream) can be used to distinguish between error and end of file)
1.3 fseek --- Adjust File Pointer to Specified Position
1.3.1 Function Prototype
c
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
1.3.2 Functionality
Move the file pointer of the specified file stream to the position of "reference position + offset", supporting forward/backward jumps. It is the core function for random reading and writing.
1.3.3 Parameters
| Parameter Name | Data Type | Meaning |
|---|---|---|
| stream | FILE * | Pointer to the target file stream |
| offset | long | Offset (number of bytes): positive = jump backward, negative = jump forward, 0 = no jump |
| whence | int | Reference position (system macro definition): • SEEK_SET: Start of file (0) • SEEK_CUR: Current pointer position (1) • SEEK_END: End of file (2) |
1.3.4 Return Value
| Return Value | Meaning |
|---|---|
| 0 | Success |
| -1 | Failure (e.g., out-of-bounds offset). Note: Jumping beyond the file size is still successful if other parameters are correct |
Note :
Restriction of 'a' mode: In 'a'/'+a' mode, after adjusting the pointer with fseek, the write operation will still force jump back to the end of the file (only reading is affected by fseek).
1.4 ftell --- Get Current File Pointer Position (Offset)
1.4.1 Function Prototype
c
#include <stdio.h>
long ftell(FILE *stream);
1.4.2 Functionality
Returns the offset (current file pointer position) of the specified file stream (number of bytes relative to the start of the file), often used with fseek (e.g., calculating file size).
1.4.3 Parameters
| Parameter Name | Data Type | Meaning |
|---|---|---|
| stream | FILE * | Pointer to the target file stream |
1.4.4 Return Value
| Return Value Type | Meaning |
|---|---|
| long | Success: Returns the offset of the specified file stream; Failure: Returns -1L |
1.5 rewind - Reset File Pointer to the Start
1.5.1 Function Prototype
c
#include <stdio.h>
void rewind(FILE *stream);
1.5.2 Functionality
Resets the file pointer to the start of the file, equivalent to fseek(stream, 0, SEEK_SET), but has no return value and is more concise.
1.5.3 Parameters
| Parameter Name | Data Type | Meaning |
|---|---|---|
| stream | FILE * | Pointer to the target file stream |
Feature: No return value, takes effect immediately after calling.
1.6 feof --- Determine if the End of File is Reached
1.6.1 Function Prototype
c
#include <stdio.h>
int feof(FILE *stream);
1.6.2 Functionality
Detects the end-of-file flag (EOF) of the specified file stream to determine whether the last byte of the file has been read (i.e., "reading completed").
Example:
c
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *fp = fopen("test.txt", "r");
if (fp == NULL) { perror("fopen"); exit(1); }
// Wrong way: Check feof first, which will read one more time (feof(fp) is non-0 only after the last fgetc returns EOF)
// while (!feof(fp)) { printf("%c", fgetc(fp)); }
// Correct way: Read first, then judge if it fails, and finally use feof to find the reason
int ch;
while ((ch = fgetc(fp)) != EOF) { // Read first
printf("%c", ch);
}
// After reading fails, judge the reason
if (feof(fp)) {
printf("\n✅ Normal: Reached the end of file\n");
} else if (ferror(fp)) {
printf("\n❌ Error: An error occurred during reading\n");
}
fclose(fp);
return 0;
}
1.6.3 Parameters
| Parameter Name | Data Type | Meaning |
|---|---|---|
| stream | FILE * | Pointer to the target file stream |
1.6.4 Return Value
| Return Value | Meaning |
|---|---|
| Non-zero value | Reached the end of the file (EOF flag is set) |
| 0 | Not reached the end of the file |
1.7 ferror --- Determine if an Error Occurred in the File Stream
1.7.1 Function Prototype
c
#include <stdio.h>
int ferror(FILE *stream);
1.7.2 Functionality
Detects the error flag of the specified file stream to determine whether read/write operations (e.g., fputc/fread) failed due to hardware/permission issues (e.g., reading a read-only file, writing to a file without permission).
1.7.3 Parameters
| Parameter Name | Data Type | Meaning |
|---|---|---|
| stream | FILE * | Pointer to the target file stream |
1.7.4 Return Value
| Return Value | Meaning |
|---|---|
| Non-zero value | An error occurred in the file stream (error flag is set) |
| 0 | No error in the file stream |
Flag Clearing: The error flag must be manually cleared by calling clearerr(stream), otherwise it will always return a non-zero value.
clearerr(fp) only does two things:
- Clears the end flag (EOF) of the file pointer fp;
- Clears the error flag (error) of the file pointer fp.
It does not change the position of the file pointer nor affect the file itself, but only resets the two state flags inside fp.
c
// Must clear the flag + reset the file pointer before reading again
clearerr(fp); // Clear EOF/error flags
fseek(fp, 0, SEEK_SET); // Return to the start of the file
1.8 fflush --- Manually Flush File Stream Cache
1.8.1 Function Prototype
c
#include <stdio.h>
int fflush(FILE *stream);
1.8.2 Functionality
Forces the unwritten content in the file stream buffer to be flushed to the target device (file/terminal), breaking the default flushing rules of "buffer full / newline / program exit".
Core Scenarios: Real-time writing (e.g., logs, monitoring data)
1.8.3 Parameters
| Parameter Name | Data Type | Meaning |
|---|---|---|
| stream | FILE * | Pointer to the target file stream; passing NULL flushes the cache of all open file streams |
1.8.4 Return Value
| Return Value | Meaning |
|---|---|
| 0 | Flush successful |
| EOF | Flush failed |
Applicable Scenarios:
- Line buffer: Real-time output is required before encountering '\n' (e.g., progress bar);
- Full buffer: File writes need to be flushed to disk immediately (to avoid data loss due to program crash);
- fclose automatically calls fflush: The buffer is flushed before closing the file, no need to call it manually.
1.9 setvbuf --- Customize File Stream Cache Strategy
1.9.1 Function Prototype
c
#include <stdio.h>
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
1.9.2 Functionality
After opening the file and before read/write operations, customize the cache type, cache address and cache size of the file stream to replace the system's default cache strategy (line buffer / full buffer / no buffer).
1.9.3 Parameters
| Parameter Name | Data Type | Meaning |
|---|---|---|
| stream | FILE * | Pointer to the target file stream (must be opened but not read/written) |
| buf | char * | Custom cache address: ・Non-NULL: Use the cache specified by the user (must be allocated in advance) ・NULL: The system automatically allocates the cache |
| mode | int | Cache mode (system macro definition): • _IOFBF: Full buffer (default for file streams) • _IOLBF: Line buffer (default for terminal streams) • _IONBF: No buffer (default for stderr) |
| size | size_t | Cache size (bytes): Valid when buf is non-NULL, it is recommended to set it to multiples of block size such as 4096/8192 |
1.9.4 Return Value
| Return Value | Meaning |
|---|---|
| 0 | Setting successful |
| Non-zero value | Setting failed |
1.9.5 Core Features
- Calling timing: Must be called after fopen and before the first read/write operation, otherwise it is invalid;
- Cache lifecycle: The user-defined buf must remain valid until the file stream is closed (to avoid stack overflow);
- Override default strategy: For example, change the terminal stream (default line buffer) to full buffer, or change the file stream to no buffer.
Example:
c
#include <stdio.h>
#include <stdlib.h>
#define BUF_SIZE 8192 // Custom cache size
int main() {
FILE *fp = fopen("test.txt", "w");
if (fp == NULL) { perror("fopen"); exit(1); }
// Allocate custom cache (heap memory to avoid stack overflow)
char *my_buf = (char *)malloc(BUF_SIZE);
if (my_buf == NULL) { perror("malloc"); fclose(fp); exit(1); }
// Set to full buffer and use custom cache
int ret = setvbuf(fp, my_buf, _IOFBF, BUF_SIZE);
if (ret != 0) {
printf("setvbuf failed\n");
free(my_buf);
fclose(fp);
exit(1);
}
// Subsequent read/write uses custom cache
fputs("Custom cache test\n", fp);
fflush(fp); // Manual flush
// Release the cache after closing
fclose(fp);
free(my_buf);
return 0;
}
Difference between fflush and fclose in Flushing
| Operation | Flush Effect | Subsequent Operations |
|---|---|---|
| fflush(fp) | Only flush the buffer, do not close the file | Can continue to read/write the file stream |
| fclose(fp) | Flush the buffer + close the file | Cannot operate the file stream anymore (invalidated) |
1.10 clearerr --- Clear File Stream Flags
The flags of feof/ferror will not be cleared automatically after being set, and need to be reset with clearerr:
c
#include <stdio.h>
void clearerr(FILE *stream);
Functionality: Clears the EOF flag and error flag of the file stream to restore the initial state.
Error Judgment:
- feof: After reading fails, judge whether it is "reached the end of the file";
- ferror: After reading fails, judge whether it is "operation error";
Core Logic: First judge whether the read/write fails (e.g., fgetc==EOF), then use these two functions to find the reason.
That's all for the content of standard IO. See you next time!