一 概述
getc 和 fread 都是C语言中用于读取文件的函数,但它们在设计目的、使用方式和性能上有显著区别。
二 基本定义
1 getc()
int getc(FILE *stream);
(1) 从文件中读取单个字符。
(2) 返回读取的字符(转换为 int 类型)。
(3)遇到文件结束或错误时返回 EOF。
2 fread()
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
(1)批量读取数据。
(2)可以读取任意类型的数据块。
(3)返回成功读取的元素个数。
三 主要区别对比
特性 getc() fread()
读取单位 单个字符 数据块(任意大小)
返回值 读取的字符 成功读取的元素数量
效率 相对较慢 效率更高(批量读取)
缓冲区使用 标准I/O缓冲区 读取到用户缓冲区
数据类型 只能读取字符 可读取任意数据类型
四 代码示例对比
1 使用 getc() 逐字符读取
#include <stdio.h>
int main() {
FILE *fp = fopen("file.txt", "r");
if (!fp) return 1;
int ch;
while ((ch = getc(fp)) != EOF) {
putchar(ch); // 处理每个字符
}
fclose(fp);
return 0;
}
2 使用 fread() 批量读取
#include <stdio.h>
int main() {
FILE *fp = fopen("data.bin", "rb");
if (!fp) return 1;
char buffer[1024];
size_t bytes_read;
// 每次读取最多1024字节
while ((bytes_read = fread(buffer, 1, sizeof(buffer), fp)) > 0) {
// 处理buffer中的数据
fwrite(buffer, 1, bytes_read, stdout);
}
fclose(fp);
return 0;
}
五 详细分析
1 性能差异
(1) getc():每次调用都有函数开销,适合小文件或需要逐字符处理的场景。
(2) fread():一次系统调用读取大量数据,减少I/O次数,适合大文件。
2 二进制文件处理
// 读取结构体数组
struct Student {
int id;
char name[20];
float score;
};
struct Student students[10];
size_t count = fread(students, sizeof(struct Student), 10, fp);
// getc() 无法直接实现这种功能
3 错误处理
(1)getc() 错误处理
int ch = getc(fp);
if (ch == EOF) {
if (feof(fp)) {
printf("到达文件末尾\n");
} else if (ferror(fp)) {
printf("读取错误\n");
}
}
(2) fread() 错误处理
size_t items = fread(data, sizeof(int), 100, fp);
if (items < 100) {
if (feof(fp)) {
printf("只读取了 %zu 个元素\n", items);
}
if (ferror(fp)) {
printf("读取错误\n");
}
}
六 选择建议
1 使用 getc() 的情况:
1 需要等待用户的输入。
2 需要检查每个字符的特殊情况。
3 文件很小或性能不是关键因素。
2 使用 fread() 的情况:
1 读取文件(如文本 、图像、音频)。
2 批量读取结构体或数组。
3 需要高性能的大文件读取。
4 网络数据传输。
七 混合使用示例
// 先读取头部信息,再逐字符处理
FILE *fp = fopen("mixed.dat", "rb");
// 用fread读取文件头
struct Header hdr;
fread(&hdr, sizeof(struct Header), 1, fp);
// 用getc逐字符读取后续内容
int ch;
while ((ch = getc(fp)) != EOF) {
// 处理每个字符
}
fclose(fp);
八 总结
(1) getc() 是字符级的读取,简单但效率较低。
(2) fread() 是块级的读取,适合高性能数据处理。