当前位置: 首页 > news >正文

MFC:初步理解序列化与反序列化(含代码实现)

       序列化与反序列化是MFC将对象数据以二进制数据流的形式进行存储和读取的机制,读、写的效率很高。通过序列化与反序列化,可以将程序中对象在内存中数据保存到文件 (磁盘) 或者从文件 (磁盘) 中读取到内存以恢复对象数据,从而实现程序对数据的持续管理。其中,序列化是指从内存到文件 (硬盘) 的存储操作;而反序列化则是指从文件 (硬盘) 到内存的读取操作。
       其程序实现的基本思路是利用文档类对象维护内存中数据,利用文件类对象维护硬盘文件数据,将二者联系起来的是归档类对象;利用这三个类的相互关联实现序列化 (含反序列化)目的。
一、序列化、反序列相关类及作用
       1、文档类CDocument,顾名思义,这个类是MFC中专职管理数据的类。而所谓序列化反序列化的概念也是针对这个类而言的,我们在这个类内可以进行序列化(含反序列化)声明,序列化声明及实现是其它所有操作的前提条件。
       通过构造继承自CDocument的自定义类,用其成员变量作为序列化或反序列化数据在内存中的载体,并通过重写它的成员虚函数Serialize实现序列化或(反序列化的具体操作,归档类对象作为参数被引入,实现文档类与归档类的关联。
       2、文件操作类CFile,作用是完成硬盘文件的读、写、存操作。成员函数包括Open (打开
文件)、Read (读文件)、Write (写文件)、Close (关闭文件) 等。文件操作类对象作为参数被归档类对象构造函数引入,与归档类对象实现关联。
       3、归档类CArchive,是用于数据流的封装类,完成内存数据的二进制读、写操作。归档类
对象首先被文档类虚函数Serialize作为参数引入;接下来,CArchive的构造函数通过其第一个
参数与文件类建立联系;并使用重载的">>"、"<<"进行读取与写入操作。CArchive对象和CFile对
象一样,用毕也需调用close函数关闭。归档类对象也有自己的成员函数,如IsStoring等。归档
类对象在三个类之间起中介作用。
二、代码实现
       这里的代码是基于VS2022 C++空项目调用MFC静态库编制的,头文件中需要包含MFC要求
的<afxwin.h>;使用的字符集为多字符集;运行结果显示在控制台窗口。具体步骤为:
1、类的声明及相关函数等的实现
      a、公开继承 CDocument 类声明一个文档类对象;
      b、类内进行序列化声明并在类外实现;
      c、类内public方式声明对象成员变量,这些成员变量是进行序列化 \ 反序列化的载体;
      d、类内声明文档类对象构造函数并在类外实现,构造函数用于接收输入数据;
      e、类内声明重写Serialize序列化虚函数并在类外实现。重写虚函数的目的是为了在
文档类与CArchive类之间建立关联,CArchive对象以参数形式进入虚函数。
2、序列化实现过程(子程序)
     a、使用CFile类对象调用Open函数创建或打开文件,文件打开方式与归档类对象读写状态
          要一致;
     b、使用CArchive类及构造函数定义归档类对象;
     c、将屏幕输入数据保存进文档类对象;
     d、使用CAchive对象将文档类对象数据写入文件;
     e、调用Close函数关闭归档类对象;
     f、调用Close函数关闭文件类对象。
3、反序列化实现过程(子程序)
     a、使用CFile类对象调用Open函数创建或打开文件 ;
     b、使用CArchive类及构造函数定义归档类对象;
     c、定义文档类指针对象;
     d、使用CAchive对象将文件数据读取到内存并转给文档类对象
     e、利用文档类对象接收数据进行屏幕显示
     f、调用Close函数关闭归档类对象
     g、调用Close函数关闭文件对象
4、主函数实现
三、代码实现及相关注释
      下面代码是基于VS C++空项目并调用MFC静态库编制,为此头文件中应包含进<afxwin.h>。字符集使用的是多字符集,运行结果显示在控制台窗口。具体代码及注释如下:

#include<afxwin.h>
#include<iostream>
using namespace std;
//公开继承CDocument方式声明文档类并构造用于存储或读取的数据类型
class CMyDoc :public CDocument
{ DECLARE_SERIAL(CMyDoc) //序列化(含反序列化)声明
public:CString m_Name; //成员变量int m_Age;CString m_Addr;CMyDoc(CString name = "", int age = 0, CString addr = ""); //声明构造函数用于赋值virtual void Serialize(CArchive& ar); //声明重写Serialize虚函数
};
//类外实现序列化(含反序列化)
IMPLEMENT_SERIAL(CMyDoc, CDocument, 2) //参3 为版本号随意定或NULL
//类外实现构造函数
CMyDoc::CMyDoc(CString name, int age, CString addr) //此处不再需要缺省值
{this->m_Name = name;this->m_Age = age;this->m_Addr = addr;
}
//类外实现重写Serialize虚函数(CArchive对象为参数)
void CMyDoc::Serialize(CArchive &archive) 
{if (archive.IsStoring()) //归档类成员函数IsStoring返回是否写入{archive << m_Name << m_Age << m_Addr;  //写入}else {archive>> m_Name >> m_Age >> m_Addr; //读取}
}
//序列化实现子程序
void dataStore() 
{ CFile file; //声明文件类对象file.Open("C:\\Users\\Administrator\\Desktop\\serial.txt", CFile::modeCreate | CFile::modeWrite,NULL);//CFile类成员函数Open:参1 文件名 参2 打开模式(文件不存在则创建、写模式) 参3 接收错误信息指针//文件后缀虽然写的是txt,但存储内容是二进制格式while (TRUE){CArchive myCAr(&file, CArchive::store, 4096, NULL); //CAchive类构造函数,此函数将CArchive对象与CFile对象连接//参1 CFile对象的指针 参2 归档状态存入 参3 缓冲区大小(默认4096) 参4 指向缓冲区的指针(缺省填NULL)cout << "在姓名处输入xxxxx退出" << endl;cout << "请输入姓名:" ;char name[64];cin >> name;if (name[0]=='x'&& name[1] == 'x'&& name[2] == 'x'&& name[3] == 'x'&& name[4] == 'x') break;cout << "请输入年龄:" ;int age;cin >> age;char addr[128];cout << "请输入住址:";cin >> addr;CMyDoc data(name, age, addr); //将输入数据保存仅文档类对象myCAr << &data; //将文档类对象传入CArchive对象(序列化)myCAr.Close(); //关闭CArchive对象}file.Close(); //关闭文件类对象
}
//反序列化子程序
void dataLoad() 
{CFile file;file.Open("C:\\Users\\Administrator\\Desktop\\serial.txt", CFile::modeRead,NULL);//各参数含义同dataStore(),只是参2为只读模式CArchive myCAr(&file, CArchive::load, 4096);//各参数含义同dataStore(),只是参2 为读取状态CMyDoc* pData = NULL; //定义文档类指针对象用来接收读取的数据while(TRUE){try {  //连续从CArchive对象读取数据传给文档类对象并进行显示myCAr >> pData; cout << pData->m_Name << " " << pData->m_Age << " " << pData->m_Addr << endl;} catch (...) { break; }} myCAr.Close(); //关闭CArchive对象file.Close(); //关闭文件类对象
}
//主函数
int main() 
{dataStore();dataLoad();system("pause");return 0;
}
/*
运行结果:
在姓名处输入xxxxx退出
请输入姓名:张三
请输入年龄:25
请输入住址:天津和平
在姓名处输入xxxxx退出
请输入姓名:李四
请输入年龄:36
请输入住址:天津红桥
在姓名处输入xxxxx退出
请输入姓名:王五
请输入年龄:27
请输入住址:天津河西
在姓名处输入xxxxx退出
请输入姓名:xxxxx
张三 25 天津和平
李四 36 天津红桥
王五 27 天津河西
请按任意键继续. . .
*/

相关文章:

MFC:初步理解序列化与反序列化(含代码实现)

序列化与反序列化是MFC将对象数据以二进制数据流的形式进行存储和读取的机制&#xff0c;读、写的效率很高。通过序列化与反序列化&#xff0c;可以将程序中对象在内存中数据保存到文件 (磁盘) 或者从文件 (磁盘) 中读取到内存以恢复对象数据&#xff0c;从而实现程序对数据的持…...

python程序控制结构

文章目录 一、python程序控制结构介绍二、顺序结构2.1、print()函数2.2、end参数2.3、input()函数 三、选择结构3.1选择结构的用途 四、循环结构4.1循环结构的构造4.1.1、循环结构的三个要素4.1.2、循环结构的一个要求4.1.3、循环结构的一个关系 4.2、循环语句4.2.1、while语句…...

【GD32】04 - Timer定时器

GD32中的定时器 GD32E230中有七个定时器&#xff0c;六种类型&#xff0c;其中通用的L4版本有两个&#xff0c;其他类型的各一个。 那我们就以通用L4这个类型来敲代码&#xff0c;其他流程是通用的。 通用L4 虽然每种类型的定时器都有自己的结构框图&#xff0c;但是其实大差…...

Golang | Leetcode Golang题解之第123题买卖股票的最佳时机III

题目&#xff1a; 题解&#xff1a; func maxProfit(prices []int) int {buy1, sell1 : -prices[0], 0buy2, sell2 : -prices[0], 0for i : 1; i < len(prices); i {buy1 max(buy1, -prices[i])sell1 max(sell1, buy1prices[i])buy2 max(buy2, sell1-prices[i])sell2 m…...

Leetcode2028. 找出缺失的观测数据

Every day a Leetcode 题目来源&#xff1a;2028. 找出缺失的观测数据 解法1&#xff1a;模拟 统计当前 m 个元素的总和 curSum sum(rolls)&#xff0c;总共 mn 个元素和为 total (m n) * mean。 排除 2 种情况&#xff1a; total - curSum > 6 * n&#xff1a;n 个…...

如何在CentOS中合理划分磁盘空间以优化系统性能

目录 前言 理想的分区方案 为什么需要单独分区 安全性 性能 管理和维护 稳定性和可靠性 升级和兼容性 结论 前言 在进行CentOS系统的安装和配置时&#xff0c;合理划分磁盘空间是确保系统性能、安全性和易于管理的关键步骤。本文将探讨如何根据系统的硬件配置和预期用途…...

算法(十一)贪婪算法

文章目录 算法简介算法概念算法举例 经典问题 -背包问题 算法简介 算法概念 贪婪算法&#xff08;Greedy&#xff09;是一种在每一步都采取当前状态下最好的或者最优的选择&#xff0c;从而希望导致结果也是全局最好或者最优的算法。贪婪算法是当下局部的最优判断&#xff0c…...

Rust之函数式语言特性:迭代器和闭包(一):概述

开发环境 Windows 11Rust 1.78.0 VS Code 1.89.1 项目工程 这次创建了新的工程minigrep. 函数式语言特性:迭代器和闭包 Rust的设计从许多现有语言和技术中获得了灵感&#xff0c;其中一个重要影响是函数式编程。函数式编程通常包括通过在参数中传递函数、从其他函数返回函数、…...

配置资源管理

一 Secret Secret 是用来保存密码、token、密钥等敏感数据的 k8s 资源&#xff0c;这类数据虽然也可以存放在 Pod 或者镜像中&#xff0c;但是放在 Secret 中是为了更方便的控制如何使用数据&#xff0c;并减少暴露的风险。 1 有三种类型&#xff1a; kubernetes.io/service…...

unity2020打包webGL时卡进程问题

我使用的2020.3.0f1c1&#xff0c;打包发布WEB版的时候会一直卡到asm2wasm.exe这个进程里&#xff0c;而且CPU占用率90%以上。 即使是打包一个新建项目的空场景也是同样的问题&#xff0c;我尝试过一直卡在这里会如何&#xff0c;结果还真打包成功了。只是打包一个空场景需要20…...

云原生架构相关技术_3.无服务器技术

1.技术特点 1.1面向特定领域的后端云服务&#xff08;BaaS&#xff09; 随着以Kubernetes为代表的云原生技术成为云计算的容器界面&#xff0c;Kubernetes成为云计算的新一代操作系统。面向特定领域的后端云服务&#xff08;BaaS&#xff09;则是这个操作系统上的服务API&…...

Leetcode:Z 字形变换

题目链接&#xff1a;6. Z 字形变换 - 力扣&#xff08;LeetCode&#xff09; 普通版本&#xff08;二维矩阵的直接读写&#xff09; 解决办法&#xff1a;直接依据题目要求新建并填写一个二维数组&#xff0c;最后再将该二维数组中的有效字符按从左到右、从上到下的顺序读取并…...

Python 3 判断文件是否存在

1 使用os.path模块 import osfile_path hello.txtif os.path.exists(file_path):print(f"文件 {file_path} 存在。") else:print(f"文件 {file_path} 不存在。") 2 使用pathlib模块 from pathlib import Pathfile_path Path(word.txt)if file_path.ex…...

(深度学习记录)第TR3周:Transformer 算法详解

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 文本的输入处理中&#xff0c;transformer会将输入文本序列的每个词转化为一个词向量&#xff0c;我们通常会选择一个合适的长度作为输入…...

谷神前端组件增强:自定义列

初始化 $gp.customColumn {}initColumnPool /*** initColumnPool* 初始化列池* * param prefix 前缀* param length 长度* * return Array 列ID数组* */ function initColumnPool (prefix, length) {return Array.from({length}, (value, index) > prefix index) } self…...

31-ESP32-S3-WIFI篇-02 Event Group (事件标记组)

ESP32-S3-WIFI 事件标记组 介绍 在ESP32-S3的WiFi驱动程序中&#xff0c;事件标记组&#xff08;Event Group&#xff09;是一个非常重要的概念。它是FreeRTOS中的一种同步机制&#xff0c;用于在任务之间传递和同步事件。在WiFi驱动程序中&#xff0c;我们使用事件标记组来通…...

构建企业级AI私有知识库

一、引言 在当今竞争激烈的市场环境中&#xff0c;企业为了保持竞争优势&#xff0c;需要高效地管理和利用内部知识资源。构建一个企业级AI私有知识库&#xff0c;不仅可以集中存储和管理企业知识&#xff0c;还能通过人工智能技术实现知识的智能化处理和利用。本文将详细介绍…...

C语言王国——杨氏矩阵

目录 1. 引言 2. 了解杨氏矩阵 3. 思路分析 4. 代码 5. 总结 1. 引言 最近在做二维数组的训练的时候发现了一个很有意思的题&#xff1a; 一看这不是杨氏矩阵嘛&#xff0c;接下来就由姜糖我带大家了解一下这个著名的矩阵。 2. 了解杨氏矩阵 通过查阅百度得知&#xff1a; …...

陪玩小程序都需要怎么做?

开发陪玩小程序需要进行全面的需求分析、功能规划、技术选型、界面设计等一系列步骤。陪玩小程序作为一种新兴的网络服务平台&#xff0c;为用户提供了寻找游戏伙伴、预约陪玩服务等功能&#xff0c;满足了用户在游戏领域的社交互动和技能提升需求。具体分析如下&#xff1a; 需…...

postgressql——子事务可见性判断 性能问题(8)

子事务可见性判断 & 性能 测试SQL BEGIN; PREPARE sel(integer) ASSELECT count(*)FROM contendWHERE id BETWEEN $1 AND $1 + 100; PREPARE upd(integer) ASUPDATE contend SET val = val + 1WHERE id IN ($1, $1 + 10, $1 + 20, $1 + 30);SAVEPOINT a; \set rnd random…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

LOOI机器人的技术实现解析:从手势识别到边缘检测

LOOI机器人作为一款创新的AI硬件产品&#xff0c;通过将智能手机转变为具有情感交互能力的桌面机器人&#xff0c;展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家&#xff0c;我将全面解析LOOI的技术实现架构&#xff0c;特别是其手势识别、物体识别和环境…...

vue3 daterange正则踩坑

<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...

用鸿蒙HarmonyOS5实现中国象棋小游戏的过程

下面是一个基于鸿蒙OS (HarmonyOS) 的中国象棋小游戏的实现代码。这个实现使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chinesechess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├──…...

MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释

以Module Federation 插件详为例&#xff0c;Webpack.config.js它可能的配置和含义如下&#xff1a; 前言 Module Federation 的Webpack.config.js核心配置包括&#xff1a; name filename&#xff08;定义应用标识&#xff09; remotes&#xff08;引用远程模块&#xff0…...

C# winform教程(二)----checkbox

一、作用 提供一个用户选择或者不选的状态&#xff0c;这是一个可以多选的控件。 二、属性 其实功能大差不差&#xff0c;除了特殊的几个外&#xff0c;与button基本相同&#xff0c;所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...