C语言fwrite函数详解:“数据快递员”

C语言fwrite函数详解:“数据快递员”一句话理解 fwrite 将内存中的二进制 包裹 批量快递到文件 仓库 中 按件打包 返回成功投递的包裹数量 函数原型 include

欢迎大家来到IT世界,在知识的湖畔探索吧!

一句话理解 fwrite

「将内存中的二进制‘包裹’批量快递到文件‘仓库’中,按件打包,返回成功投递的包裹数量!」


函数原型

#include <stdio.h> // 必须包含头文件 size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

欢迎大家来到IT世界,在知识的湖畔探索吧!

入口参数

参数

类型

比喻解释

ptr

const void*

内存「包裹」的地址(要发送的数据

size

size_t

每个包裹的大小(单位:字节)

nmemb

size_t

希望快递的包裹件数

stream

FILE*

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

返回参数

返回值

含义

size_t

实际成功快递的包裹件数(≤ nmemb)


核心功能图解

欢迎大家来到IT世界,在知识的湖畔探索吧!内存包裹内容:[][][][][][](每个水果占2字节) 调用 fwrite(ptr, 2, 3, file) → 发送3个包裹(每个2字节) 文件仓库内容:[][][][][][] 返回 3(成功发送3件)

代码实例1:保存结构体数组

场景:存档学生成绩

#include <stdio.h> #include <stdlib.h> // 定义「包裹」结构 typedef struct { char name[20]; int score; } Student; int main() { Student classroom[3] = { {"Alice", 90}, {"Bob", 85}, {"Charlie", 95} }; FILE *file = fopen("students.dat", "wb"); // 二进制写模式 if (!file) { perror("❌ 仓库门打不开"); return 1; } // 快递数据:每件包裹=1个Student,发送3件 size_t shipped = fwrite(classroom, sizeof(Student), 3, file); if (shipped < 3) { printf("⚠️ 只成功发送%zu件包裹,可能仓库爆满了\n", shipped); } else { printf("✅ 3名学生数据已安全存档\n"); } fclose(file); return 0; }

代码实例2:生成图片文件

场景:创建纯色BMP位图

欢迎大家来到IT世界,在知识的湖畔探索吧!#include <stdio.h> #pragma pack(1) // 禁用内存对齐(确保结构体紧凑存储) // BMP文件头结构 typedef struct { char magic[2]; // "BM" int file_size; // 文件总大小 short reserved[2]; // 保留字段 int data_offset; // 像素数据偏移量 } BMPHeader; int main() { BMPHeader header = { {'B', 'M'}, // 魔数 54 + 640*480*3, // 文件大小=头54字节+RGB数据 {0, 0}, // 保留 54 // 像素数据从54字节开始 }; FILE *image = fopen("red.bmp", "wb"); if (!image) { perror("创建图片失败"); return 1; } // 快递文件头(1个包裹,包裹大小=sizeof(BMPHeader)) if (fwrite(&header, sizeof(BMPHeader), 1, image) != 1) { printf(" 文件头写入失败\n"); fclose(image); return 1; } // 生成纯红色像素数据(640x480分辨率) unsigned char red[3] = {0, 0, 255}; // BMP使用BGR格式 for (int i = 0; i < 640*480; i++) { if (fwrite(red, 3, 1, image) != 1) { // 每个像素3字节 printf(" 像素数据写入失败\n"); break; } } fclose(image); printf(" 红色BMP图片已生成\n"); return 0; }

技术细节剖析

1.参数顺序的黄金法则

// ❌ 常见错误:size 和 nmemb 写反 fwrite(buffer, 100, 1, file); // 发送1个100字节的包裹 fwrite(buffer, 1, 100, file); // 发送100个1字节的包裹(效果相同,但语义不同)

2.返回值隐藏的密码

返回值

含义分析

= nmemb

完美发送所有包裹

< nmemb

可能磁盘空间不足或文件错误

0

完全发送失败

3.二进制模式的必要性

  • 在Windows系统中必须用 “wb” 模式,否则可能意外修改数据:
欢迎大家来到IT世界,在知识的湖畔探索吧!// 错误示范:文本模式写入二进制数据 FILE *file = fopen("data.bin", "w"); // 导致数据损坏(如0x0A被改为0x0D0A)

⚠️ 致命误区

1.内存对齐陷阱

#pragma pack(1) // 必须禁用对齐,否则结构体可能有空隙 typedef struct { char a; int b; // 默认对齐后结构体大小为8字节(非5字节) } CustomStruct;

2.缓冲区溢出

欢迎大家来到IT世界,在知识的湖畔探索吧!int arr[5] = {1,2,3,4,5}; // 危险!试图写入6个int,但数组只有5个元素 fwrite(arr, sizeof(int), 6, file); // 发送越界数据!

️ 高级技巧:增量写入大文件

#define CHUNK_SIZE 4096 // 每次发送4KB unsigned char buffer[CHUNK_SIZE]; size_t total_sent = 0; while (有数据要发送) { fill_buffer(buffer, CHUNK_SIZE); // 填充数据 size_t sent = fwrite(buffer, 1, CHUNK_SIZE, file); total_sent += sent; if (sent < CHUNK_SIZE) { perror("⚠️ 快递中途停止"); break; } } printf(" 总发送量:%zu 字节\n", total_sent);

对比 fread

操作

方向

常见用途

fwrite

内存→文件

保存数据、序列化

fread

文件→内存

加载数据、反序列化


总结

  • 核心功能:批量写入二进制数据到文件
  • 必用场景:保存游戏存档、生成图像/音频、日志记录
  • 类比记忆:就像用传送带把工厂流水线上的标准货箱批量装船,fwrite 是C语言输出二进制数据的「物流指挥官」

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/111863.html

(0)
上一篇 8分钟前
下一篇 2025年 1月 15日 下午8:55

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信