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

C语言fread函数详解:“数据搬运工”

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

一句话理解 fread

「从文件的‘仓库’中批量搬运二进制‘货物’到内存‘卡车’中,按需装货,返回实际搬运的货物数量!」


函数原型

c

复制

#include   // 必须包含头文件
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

入口参数

参数

类型

比喻解释

ptr

void*

内存「卡车」的地址(存放数据)

size

size_t

每件「货物」的大小(单位:字节)

nmemb

size_t

希望搬运的货物件数

stream

FILE*

文件「仓库」的门(文件指针)

返回参数

返回值

含义

size_t

实际成功搬运的货物件数(≤ nmemb)


核心功能图解

假设文件内容(二进制):[A][A][B][B][C][C](每个字母占2字节)
调用 fread(ptr, 2, 3, file) → 搬运3件货物(每件2字节)
内存卡车内容:[A][A][B][B][C][C]
返回 3(成功搬运3件)

代码实例1:读取结构体数组

场景:读取学生成绩存档

#include 
#include 

// 定义「货物」结构
typedef struct {
    char name[20];
    int score;
} Student;

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

    Student classroom[3];  // 准备3个学生的「卡车」

    // 从文件搬运数据:每件货物=1个Student,最多搬3件
    size_t loaded = fread(classroom, sizeof(Student), 3, file);

    if (loaded < 3) {
        printf(" 只搬运了%zu件货物,可能仓库没货了\n", loaded);
    } else {
        printf(" 成功搬运3名学生数据\n");
        for (int i = 0; i < 3; i++) {
            printf("学生%d: %s, 分数=%d\n", 
                   i+1, classroom[i].name, classroom[i].score);
        }
    }

    fclose(file);
    return 0;
}

代码实例2:读取图片文件头

场景:解析PNG文件特征

#include 

// PNG文件头特征(固定8字节)
#define PNG_HEADER_SIZE 8

int main() {
    FILE *image = fopen("photo.png", "rb");
    if (!image) {
        perror("图片仓库失联");
        return 1;
    }

    unsigned char header[PNG_HEADER_SIZE];  // 准备8字节的「小推车」

    // 搬运文件头:每件1字节,搬8件
    if (fread(header, 1, PNG_HEADER_SIZE, image) != PNG_HEADER_SIZE) {
        printf(" 文件头不完整\n");
        fclose(image);
        return 1;
    }

    // 检查PNG特征(89 50 4E 47 0D 0A 1A 0A)
    if (header[0] == 0x89 && header[1] == 0x50 && 
        header[2] == 0x4E && header[3] == 0x47) {
        printf(" 这是合法的PNG图片\n");
    } else {
        printf(" 文件头异常,疑似损坏\n");
    }

    fclose(image);
    return 0;
}

技术细节剖析

1.参数顺序的黄金法则

//  常见错误:size 和 nmemb 写反
fread(buffer, 100, 1, file);  // 搬运1件100字节的货物
fread(buffer, 1, 100, file);  // 搬运100件1字节的货物(效果相同,但语义不同)

2.返回值隐藏的密码

返回值

含义分析

= nmemb

完美搬运所有货物

< nmemb

可能遇到文件尾(EOF)或错误

0

仓库已空或发生错误

3.二进制模式的必要性

  • 在Windows系统中,必须用 "rb" 模式打开文件,否则会遇到换行符转换问题:
// 错误示范:文本模式读取二进制文件 FILE *file = fopen("data.bin", "r"); // 导致数据损坏

致命误区

1.缓冲区溢出

int arr[5];
// 危险!试图读取6个int,但卡车只能装5个
fread(arr, sizeof(int), 6, file);  // 内存越界!

2.类型不匹配

float data[10];
// 错误!文件存储的是double类型
fread(data, sizeof(double), 10, file);  // 数据解析错误

高级技巧:分块读取大文件

#define CHUNK_SIZE 4096  // 4KB的「卡车容量」
unsigned char buffer[CHUNK_SIZE];
size_t total_read = 0;

while (1) {
    size_t read = fread(buffer, 1, CHUNK_SIZE, file);
    total_read += read;
    if (read < CHUNK_SIZE) {
        if (feof(file)) {
            printf(" 全部货物搬运完成,总量:%zu字节\n", total_read);
        } else if (ferror(file)) {
            perror("搬运事故");
        }
        break;
    }
    // 处理本批次数据...
}

对比 fwrite

操作

方向

常见用途

fread

文件→内存

加载数据、反序列化

fwrite

内存→文件

保存数据、序列化


总结

  • 核心功能:批量读取二进制数据到内存
  • 必用场景:加载游戏存档、处理图像/音频、网络数据传输
  • 类比记忆:就像用叉车从仓库中成批搬运标准规格的集装箱到卡车上,fread 是C语言处理二进制数据的「物流专家」

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

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

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

标签: ts void
分享给朋友:

“C语言fread函数详解:“数据搬运工”” 的相关文章

给大家分享几个漂亮的 Arch Linux 发行版

ArchLinux是一款备受欢迎的、面向技术爱好者和Linux专业人士的发行版。它以其简洁、灵活和高度可定制的特点而闻名,但对于一些人来说,配置和设置ArchLinux可能会有一些挑战。为了方便那些希望快速入门并且喜欢漂亮外观的人,我们想分享几个令人赞叹的ArchLinux发行版,它们提供了美观的界...

发行版Vanilla OS 2发布稳定版:彻底重写、改变使用Linux的方式

Vanilla OS 是去年崭露头角的 Linux 发行版,最初的 1.0 版本基于 Ubuntu 构建 —— 亮点之一是系统核心“不可变”。后来改用 Debian 测试分支 (Debian Sid),免费且开源,默认桌面环境是 GNOME。什么是不可变 Linux 发行版?不可变发行版确保操作系统...

12种JavaScript中最常用的数组操作整理汇总

数组是最常见的数据结构之一,我们需要绝对自信地使用它。在这里,我将列出 JavaScript 中最重要的几个数组常用操作片段,包括数组长度、替换元素、去重以及许多其他内容。1、数组长度大多数人都知道可以像这样得到数组的长度:const arr = [1, 2, 3]; console.log(a...

Vue学习笔记之动态路由的参数传递应用及技巧

路由的参数传递:①通过params的类型· 配置路由格式:/router/:id· 传递的方式:在path后面跟上对应的值· 传递后形成的路径:/router/list,/router/profile这个就是前两篇中提到的"动态路由"中有应用过这个方法:②通过query的类型(对象方...

从 Vue2.0 到 React17——React 开发入门

作者:佚名来源:前端大全前言找工作时发现有一些公司是以React作为技术栈的,而且薪资待遇都不错,为了增加生存的筹码,所以还是得去学一下React,增加一项求生技能。因为我用Vue2.0开发项目已经四年了,故用Vue2.0开发项目的思路来学习React。前端项目是由一个个页面组成的,对于Vue来说,...

「干货」Vue+Element前端导入导出Excel

作者:xrkffgg转发链接:https://segmentfault.com/a/11900000189936191 前言1.1 业务场景由前台导入Excel表格,获取批量数据。根据一个数组导出Excel表格。2 实现原理2.1 引入工具库file-saver、xlsx、script-loader...