当前位置:首页 > 技术分析 > 正文内容

C语言fread函数详解:“工厂传送带”

ruisui882个月前 (03-11)技术分析9

一句话理解 fread

「fread 就像工厂的传送带,从文件仓库中批量搬运二进制‘货物’到内存卡车,高效且精准!」


函数原型

#include 
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);

入口参数

参数

类型

比喻解释

ptr

void*

内存中的「卡车」(存储数据的缓冲区)

size

size_t

每个「货物单元」的大小(字节)

count

size_t

希望搬运的货物单元数量

stream

FILE*

数据来源的「仓库门」(文件指针)

返回参数

返回值

含义

size_t

实际成功搬运的货物单元数量(≤count)

0

仓库已空或传送故障


核心功能图解

文件内容:■■■■■■■■■■■■■■■■■■■■(20字节)
fread(buffer, 5, 3, file) → 搬运15字节,返回3(成功搬运3个5字节单元)

代码实例:货物搬运实战

场景1:读取结构体数组(学生档案)

#include 

typedef struct {
    char name[20];
    int age;
    float score;
} Student;

int main() {
    FILE *file = fopen("students.dat", "rb");  // 二进制读模式
    if (!file) {
        perror(" 档案库门打不开");
        return 1;
    }

    Student classroom[3];  // 准备3个学生的“卡车”
    size_t loaded = fread(classroom, sizeof(Student), 3, file);

    if (loaded < 3) {
        printf(" 只加载了%zu名学生数据\n", loaded);
        if (feof(file)) printf("(档案已读完)\n");
        if (ferror(file)) perror("(搬运故障)");
    }

    fclose(file);
    return 0;
}

场景2:分块读取大文件(防止内存溢出)

#include 

#define CHUNK_SIZE 4096  // 每次搬运4KB

int main() {
    FILE *video = fopen("movie.mp4", "rb");
    if (!video) return 1;

    unsigned char buffer[CHUNK_SIZE];  // 4KB的“卡车”
    size_t total_read = 0;

    while (!feof(video)) {
        size_t read = fread(buffer, 1, CHUNK_SIZE, video);
        total_read += read;
        // 处理本块数据(如加密/压缩/传输)
    }

    printf("总搬运量:%zu KB\n", total_read / 1024);
    fclose(video);
    return 0;
}

场景3:错误处理(检测文件完整性)

#include 

int verify_file(const char *filename, size_t expected_size) {
    FILE *file = fopen(filename, "rb");
    if (!file) return -1;

    char buffer[1024];
    size_t total = 0;
    while (!feof(file)) {
        size_t read = fread(buffer, 1, sizeof(buffer), file);
        total += read;
    }

    fclose(file);
    return (total == expected_size) ? 0 : 1;  // 验证文件大小
}

技术细节剖析

1. size 和 count 的黄金组合

  • 乘法关系:总读取字节数 = size * count
  • 灵活控制
// 两种等效写法:
fread(buf, 1, 100, file);  // 读100个1字节单元 → 100字节  
fread(buf, 100, 1, file);  // 读1个100字节单元 → 100字节  

2. 返回值隐藏的密码

返回值

含义分析

=count

完美搬运所有单元

<count

文件剩余不足或读取错误

0

文件已结束或严重错误


常见错误与修复

1. 缓冲区溢出(卡车太小)

int data[10];
// 危险!文件可能包含超过40字节数据
fread(data, sizeof(int), 20, file);  // 卡车容量仅40字节,却试图搬运80字节!

修复

int data[20];  // 正确匹配容量
fread(data, sizeof(int), 20, file);

2. 忘记二进制模式(文本文件污染)

FILE *file = fopen("image.jpg", "r");  //  文本模式破坏二进制数据
fread(...);

修复

FILE *file = fopen("image.jpg", "rb"); //  二进制模式

高级技巧:内存映射文件

// 结合fread实现高效数据处理(伪代码)
while (!feof(file)) {
    fread(buffer, 1, CHUNK_SIZE, file);
    process_data(buffer);  // 加密/解密/分析
    upload_to_network(buffer);  // 分块传输
}

总结表格

特性

说明

核心功能

批量读取二进制数据

适用场景

结构体/数组存储、大文件处理

性能

适合块状读取,效率远超逐字节

安全准则

检查返回值,匹配缓冲区大小


总结

  • 像智能传送带:fread 是C语言中处理二进制数据的核心工具,特点:
    1 批量操作:高效搬运数据块,减少IO次数
    2 精准控制:通过 size 和 count 精细调节读取粒度
    3 跨平台兼容:统一处理文本/二进制文件(需正确设置模式)
  • 使用口诀
    「算好尺寸,检查货量;二进制门,必须打开;返回值验,错误不漏!」

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/2684.html

标签: ts void
分享给朋友:

“C语言fread函数详解:“工厂传送带”” 的相关文章

学会使用Vue JSX,一车老干妈都是你的

作者:子君转发链接:https://mp.weixin.qq.com/s/eAOivpHeowLShfwPfW8-BA?君自前端来,应知前端事。需求时时变,bug改不完。?连续几篇文章,每篇都有女神,被老铁给吐槽了,今天不提了女神了,反正女神都是别人的(扎心了)。这两天小编看了腾讯与老干妈的事情,晚...

迁移GIT仓库并带有历史提交记录

迁移git仓库开发在很多时候,会遇到一个问题。GIT仓库的管理,特别是仓库的迁移。我需要保留已有的历史记录,而不是重新开发,重头再来。我们可以这样做:使用--mirror模式会把本地的分支都克隆。// 先用--bare克隆裸仓库 git clone git@gitee.com:xxx/testApp...

壹啦罐罐 Android 手机里的 Xposed 都装了啥

这是少数派推出的系列专题,叫做「我的手机里都装了啥」。这个系列将邀请到不同的玩家,从他们各自的角度介绍手机中最爱的或是日常使用最频繁的 App。文章将以「每周一篇」的频率更新,内容范围会包括 iOS、Android 在内的各种平台和 App。本期继续歪楼,由少数派撰稿作者@壹啦罐罐介绍他正在使用的...

高效使用 Vim 编辑器的 10 个技巧

在 Reverb,我们使用 MacVim 来标准化开发环境,使配对更容易,并提高效率。当我开始使用 Reverb 时,我以前从未使用过 Vim。我花了几个星期才开始感到舒服,但如果没有这样的提示,可能需要几个月的时间。这里有十个技巧可以帮助你在学习使用 Vim 时提高效率。1. 通过提高按键重复率来...

html5+css3做的响应式企业网站前端源码

大家好,今天给大家介绍一款,html5+css3做的响应式企业网站前端源码 (图1)。送给大家哦,获取方式在本文末尾。首页banner幻灯片切换特效(图2)首页布局简约合理(图3)关于我们页面(图4)商品列表(图5)商品详情(图6)服务介绍(图7)新闻列表(图8)联系我们(图9)源码完整,需要的朋友...

js中数组filter方法的使用和实现

定义filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。语法var newArray = arr.filter(callback(element[, index[, selfArr]])[, thisArg])参数callback循环数组每个元素时调用的回调函数。回调函...