云计算、AI、云原生、大数据等一站式技术学习平台

网站首页 > 教程文章 正文

C语言fwrite函数详解:“二进制快递员”

jxf315 2025-03-11 17:16:11 教程文章 33 ℃

一句话理解 fwrite

「fwrite 就像一位高效的二进制快递员,将内存中的‘货物’(数据块)批量打包,精准投递到文件仓库,支持任意数据类型!」


函数原型

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

入口参数

参数

类型

比喻解释

ptr

const void*

要投递的「货物地址」(数据指针)

size

size_t

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

count

size_t

希望投递的货物单元数量

stream

FILE*

目标「仓库门」(文件指针)

返回参数

返回值

含义

size_t

实际成功投递的货物单元数量(≤count)

0

投递失败(如磁盘满或文件未打开)


核心功能图解

内存货物:■■■■■■■■■■(10字节)  
fwrite(ptr, 2, 5, file) → 投递5个2字节单元(共10字节),返回5

代码实例:快递实战

场景1:保存结构体数组(学生数据存档)

#include 

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

int main() {
    Student class[3] = {
        {"Alice", 20, 95.5},
        {"Bob", 19, 88.0},
        {"Charlie", 21, 76.5}
    };

    FILE *file = fopen("students.dat", "wb"); // 二进制写模式打开仓库门
    if (!file) {
        perror(" 仓库门打不开");
        return 1;
    }

    // 投递3个学生数据单元
    size_t shipped = fwrite(class, sizeof(Student), 3, file);
    
    if (shipped < 3) {
        printf(" 只投递了%zu份档案(磁盘可能已满)\n", shipped);
    } else {
        printf(" 学生档案已安全入库!\n");
    }

    fclose(file);
    return 0;
}

场景2:分块写入大文件(视频备份)

#include 
#define CHUNK_SIZE 4096  // 每次投递4KB

int main() {
    FILE *source = fopen("input.mp4", "rb");
    FILE *backup = fopen("backup.mp4", "wb");
    if (!source || !backup) return 1;

    unsigned char buffer[CHUNK_SIZE];  // 4KB的“快递箱”
    size_t total_shipped = 0;

    while (!feof(source)) {
        // 从源文件读取一块数据
        size_t read = fread(buffer, 1, CHUNK_SIZE, source);
        // 投递到备份文件
        size_t written = fwrite(buffer, 1, read, backup);
        if (written < read) {
            printf(" 第%zu块投递失败\n", total_shipped / CHUNK_SIZE);
            break;
        }
        total_shipped += written;
    }

    printf("总投递量:%.2f MB\n", (double)total_shipped / (1024*1024));
    fclose(source);
    fclose(backup);
    return 0;
}

场景3:错误处理(磁盘空间监控)

#include 

int save_data(const char *filename, const void *data, size_t size) {
    FILE *file = fopen(filename, "wb");
    if (!file) return -1;

    size_t written = fwrite(data, 1, size, file);
    fclose(file);

    if (written < size) {
        printf(" 数据未完全写入(剩余%zu字节)\n", size - written);
        return 1;
    }
    return 0;
}

int main() {
    char big_data[1024*1024] = {0};  // 1MB数据
    if (save_data("bigfile.bin", big_data, sizeof(big_data)) != 0) {
        printf("请检查磁盘空间!\n");
    }
    return 0;
}

技术细节剖析

1. size 和 count 的黄金法则

  • 乘法关系:总写入字节数 = size * count
  • 灵活组合
int arr[100];
fwrite(arr, sizeof(int), 100, file);   // 写法1:100个int单元  
fwrite(arr, 1, sizeof(arr), file);     // 写法2:1个400字节单元(假设int为4字节)

2. 二进制模式的重要性

  • 文本文件陷阱:在Windows中,文本模式会转换换行符(\n→\r\n),破坏二进制数据。
  • 正确打开方式
FILE *file = fopen("data.bin", "wb"); //  二进制模式

常见错误与修复

1. 缓冲区指针错误

int *data = malloc(10 * sizeof(int));
// 错误!指针未初始化或已释放
fwrite(data, sizeof(int), 10, file);  

修复

int data[10] = {0};  // 确保指针有效
fwrite(data, sizeof(int), 10, file);

2. 文件未以二进制模式打开

FILE *file = fopen("image.png", "w");  //  文本模式破坏数据
fwrite(pixels, 1, size, file);  

修复

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

高级技巧:内存直接转储

#include 

typedef struct {
    int id;
    double value;
    char tag[4];
} SensorData;

void log_sensor(FILE *file, const SensorData *data) {
    // 直接投递结构体(确保文件以二进制模式打开)
    if (fwrite(data, sizeof(SensorData), 1, file) != 1) {
        perror("传感器数据投递失败");
    }
}

总结表格

特性

说明

核心功能

批量写入二进制数据

适用场景

结构体/数组存储、大文件备份

性能

高效,适合块状写入

安全准则

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


总结

  • 像专业快递员:fwrite 是C语言中处理二进制输出的核心工具,特点:
    1 批量高效:减少IO操作,提升写入速度
    2 精准控制:通过 size 和 count 调节写入粒度
    3 跨平台可靠:二进制模式确保数据一致性
  • 使用口诀
    「二进制门,必须打开;算好尺寸,验明货量;错误必查,安全送达!」
最近发表
标签列表