C++如何用fwrite将结构体存入二进制文件实现对象序列化

来源:站长素材作者:南京SEO公司头衔:草根站长
导读:本期聚焦于小伙伴创作的《C++如何用fwrite将结构体存入二进制文件实现对象序列化》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++如何用fwrite将结构体存入二进制文件实现对象序列化》有用,将其分享出去将是对创作者最好的鼓励。

在C++程序开发中,经常会遇到需要将内存中的结构体对象持久化保存到文件的需求,将结构体存入二进制文件是一种高效的实现方式,fwrite函数作为C标准库中的二进制写入函数,能够很好地完成这一任务,实现简单的对象序列化功能。

基础结构体序列化实现

对于不包含指针成员、内存布局连续的基础结构体,使用fwrite直接写入二进制文件是最简单的方式。首先需要定义结构体类型,然后创建结构体实例并赋值,最后调用fwrite将结构体数据写入文件。

下面是一个简单的示例代码,演示基础结构体的序列化过程:

#include <stdio.h>
#include <string.h>

// 定义基础结构体,无指针成员
struct Student {
    int id;
    char name[20];
    float score;
};

int main() {
    // 创建并初始化结构体对象
    Student stu;
    stu.id = 1001;
    strcpy(stu.name, "张三");
    stu.score = 89.5f;

    // 以二进制写入模式打开文件
    FILE* file = fopen("student.dat", "wb");
    if (file == NULL) {
        printf("文件打开失败n");
        return 1;
    }

    // 使用fwrite将结构体写入二进制文件
    // 参数依次为:数据地址、单个数据字节数、数据个数、文件指针
    size_t writeCount = fwrite(&stu, sizeof(Student), 1, file);
    if (writeCount != 1) {
        printf("数据写入失败n");
    } else {
        printf("结构体序列化成功n");
    }

    // 关闭文件
    fclose(file);
    return 0;
}

从二进制文件读取结构体数据

序列化后的数据需要能够读取回来,对应的读取操作可以使用fread函数完成,流程和写入类似,先打开二进制文件,再读取数据到结构体实例中。

读取的示例代码如下:

#include <stdio.h>

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

int main() {
    Student stu;

    // 以二进制读取模式打开文件
    FILE* file = fopen("student.dat", "rb");
    if (file == NULL) {
        printf("文件打开失败n");
        return 1;
    }

    // 使用fread读取二进制数据到结构体
    size_t readCount = fread(&stu, sizeof(Student), 1, file);
    if (readCount != 1) {
        printf("数据读取失败n");
    } else {
        printf("读取到的学生信息:n");
        printf("ID:%dn", stu.id);
        printf("姓名:%sn", stu.name);
        printf("分数:%.2fn", stu.score);
    }

    fclose(file);
    return 0;
}

需要注意的核心问题

内存对齐影响

编译器默认会对结构体进行内存对齐,不同编译器、不同平台的对齐规则可能存在差异,这会导致结构体的实际大小不等于成员大小的简单相加。如果使用fwrite写入,读取时如果结构体对齐规则变化,就会出现数据解析错误。

可以通过编译器指令取消内存对齐,保证结构体布局的一致性,以GCC编译器为例,可以使用__attribute__((packed))属性:

// 取消内存对齐的结构体定义
struct __attribute__((packed)) Student {
    int id;
    char name[20];
    float score;
};

指针成员处理

如果结构体包含指针成员,直接使用fwrite写入只会保存指针本身的值(也就是内存地址),而不会保存指针指向的实际数据。当程序重启后,原来的内存地址已经无效,读取到的指针值也没有意义,还会导致内存访问错误。

对于包含指针成员的结构体,需要先序列化指针指向的数据,读取时再重新分配内存并赋值指针。例如结构体包含字符串指针的场景:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 包含指针成员的结构体
struct Person {
    int age;
    char* name; // 指针成员
};

int main() {
    Person p;
    p.age = 25;
    p.name = (char*)malloc(20);
    strcpy(p.name, "李四");

    FILE* file = fopen("person.dat", "wb");
    if (file == NULL) {
        printf("文件打开失败n");
        free(p.name);
        return 1;
    }

    // 先写入age
    fwrite(&p.age, sizeof(int), 1, file);
    // 写入name字符串的长度
    int nameLen = strlen(p.name) + 1;
    fwrite(&nameLen, sizeof(int), 1, file);
    // 写入name指向的实际字符串
    fwrite(p.name, sizeof(char), nameLen, file);

    fclose(file);
    free(p.name);

    // 读取逻辑
    Person p2;
    file = fopen("person.dat", "rb");
    if (file == NULL) {
        printf("文件打开失败n");
        return 1;
    }

    fread(&p2.age, sizeof(int), 1, file);
    int readLen;
    fread(&readLen, sizeof(int), 1, file);
    p2.name = (char*)malloc(readLen);
    fread(p2.name, sizeof(char), readLen, file);

    printf("读取到的人员信息:n");
    printf("年龄:%dn", p2.age);
    printf("姓名:%sn", p2.name);

    fclose(file);
    free(p2.name);
    return 0;
}

跨平台兼容性

不同平台的大小端字节序、类型长度可能存在差异,比如int类型在有的平台是2字节,有的是4字节,直接使用fwrite写入的结构体在跨平台读取时也会出现问题。如果需要在不同平台间传输序列化数据,还需要额外处理字节序和类型长度的兼容问题。

适用场景总结

使用fwrite实现结构体二进制序列化适合以下场景:单平台运行、结构体无指针成员或者已经做好指针数据处理、不需要跨平台兼容的简单数据持久化需求。如果是复杂场景或者需要跨平台使用,建议使用更成熟的序列化库来实现,避免手动处理各类兼容问题。

C++fwrite结构体二进制文件对象序列化修改时间:2026-07-07 11:54:38

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。