在C语言中,文件操作是程序开发中非常常见的一部分。`fread` 和 `fwrite` 是用于对文件进行二进制读写操作的两个重要函数。它们与 `fscanf` 和 `fprintf` 不同,后者主要用于文本格式的数据读写。而 `fread` 和 `fwrite` 则更适合处理结构体、数组等复杂数据类型,能够更高效地进行数据的读取与存储。
一、函数原型
`fread` 和 `fwrite` 的定义如下:
```c
size_t fread(void ptr, size_t size, size_t nmemb, FILE stream);
size_t fwrite(const void ptr, size_t size, size_t nmemb, FILE stream);
```
- `ptr`:指向缓冲区的指针,用于存放读取或写入的数据。
- `size`:每个元素的大小(以字节为单位)。
- `nmemb`:要读取或写入的元素个数。
- `stream`:文件指针,指向已打开的文件。
返回值是成功读取或写入的元素个数,如果发生错误则返回小于预期的数值。
二、使用示例
1. 使用 `fwrite` 写入数据
假设我们有一个结构体,用于保存学生信息:
```c
typedef struct {
int id;
char name[50];
float score;
} Student;
```
我们可以将一个学生的信息写入文件中:
```c
Student s = {1, "Alice", 95.5};
FILE fp = fopen("students.dat", "wb"); // 以二进制写方式打开
if (fp == NULL) {
printf("无法打开文件\n");
return -1;
}
fwrite(&s, sizeof(Student), 1, fp); // 写入一个学生数据
fclose(fp);
```
注意,这里使用了 `"wb"` 模式,表示以二进制方式写入。如果文件不存在,则会自动创建;如果存在,则会被覆盖。
2. 使用 `fread` 读取数据
接下来,我们从同一个文件中读取数据:
```c
Student s;
FILE fp = fopen("students.dat", "rb"); // 以二进制读方式打开
if (fp == NULL) {
printf("无法打开文件\n");
return -1;
}
size_t result = fread(&s, sizeof(Student), 1, fp);
if (result == 1) {
printf("ID: %d, Name: %s, Score: %.2f\n", s.id, s.name, s.score);
} else {
printf("读取失败\n");
}
fclose(fp);
```
三、注意事项
1. 数据类型一致性:在使用 `fread` 和 `fwrite` 时,必须确保读取和写入的数据类型完全一致,否则可能导致数据解析错误。
2. 文件模式选择:`fopen` 的模式参数应根据操作类型选择,如 `"rb"` 或 `"wb"`,避免出现文本模式下的换行符转换问题。
3. 内存对齐问题:在某些平台上,结构体可能会因为内存对齐而占用更多空间,因此使用 `sizeof()` 获取结构体大小时需谨慎。
4. 错误处理:应检查 `fread` 和 `fwrite` 的返回值,确保数据读写正确完成。
四、总结
`fread` 和 `fwrite` 是C语言中处理二进制文件的核心函数,适用于结构体、数组等复杂数据类型的读写。相比文本模式的读写方式,它们具有更高的效率和灵活性。在实际开发中,合理使用这两个函数可以有效提升程序的性能和数据处理能力。掌握其用法对于理解底层文件操作至关重要。