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将对象数据以二进制数据流的形式进行存储和读取的机制,读、写的效率很高。通过序列化与反序列化,可以将程序中对象在内存中数据保存到文件 (磁盘) 或者从文件 (磁盘) 中读取到内存以恢复对象数据,从而实现程序对数据的持…...
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中有七个定时器,六种类型,其中通用的L4版本有两个,其他类型的各一个。 那我们就以通用L4这个类型来敲代码,其他流程是通用的。 通用L4 虽然每种类型的定时器都有自己的结构框图,但是其实大差…...
Golang | Leetcode Golang题解之第123题买卖股票的最佳时机III
题目: 题解: 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 题目来源:2028. 找出缺失的观测数据 解法1:模拟 统计当前 m 个元素的总和 curSum sum(rolls),总共 mn 个元素和为 total (m n) * mean。 排除 2 种情况: total - curSum > 6 * n:n 个…...
如何在CentOS中合理划分磁盘空间以优化系统性能
目录 前言 理想的分区方案 为什么需要单独分区 安全性 性能 管理和维护 稳定性和可靠性 升级和兼容性 结论 前言 在进行CentOS系统的安装和配置时,合理划分磁盘空间是确保系统性能、安全性和易于管理的关键步骤。本文将探讨如何根据系统的硬件配置和预期用途…...
算法(十一)贪婪算法
文章目录 算法简介算法概念算法举例 经典问题 -背包问题 算法简介 算法概念 贪婪算法(Greedy)是一种在每一步都采取当前状态下最好的或者最优的选择,从而希望导致结果也是全局最好或者最优的算法。贪婪算法是当下局部的最优判断,…...
Rust之函数式语言特性:迭代器和闭包(一):概述
开发环境 Windows 11Rust 1.78.0 VS Code 1.89.1 项目工程 这次创建了新的工程minigrep. 函数式语言特性:迭代器和闭包 Rust的设计从许多现有语言和技术中获得了灵感,其中一个重要影响是函数式编程。函数式编程通常包括通过在参数中传递函数、从其他函数返回函数、…...
配置资源管理
一 Secret Secret 是用来保存密码、token、密钥等敏感数据的 k8s 资源,这类数据虽然也可以存放在 Pod 或者镜像中,但是放在 Secret 中是为了更方便的控制如何使用数据,并减少暴露的风险。 1 有三种类型: kubernetes.io/service…...
unity2020打包webGL时卡进程问题
我使用的2020.3.0f1c1,打包发布WEB版的时候会一直卡到asm2wasm.exe这个进程里,而且CPU占用率90%以上。 即使是打包一个新建项目的空场景也是同样的问题,我尝试过一直卡在这里会如何,结果还真打包成功了。只是打包一个空场景需要20…...
云原生架构相关技术_3.无服务器技术
1.技术特点 1.1面向特定领域的后端云服务(BaaS) 随着以Kubernetes为代表的云原生技术成为云计算的容器界面,Kubernetes成为云计算的新一代操作系统。面向特定领域的后端云服务(BaaS)则是这个操作系统上的服务API&…...
Leetcode:Z 字形变换
题目链接:6. Z 字形变换 - 力扣(LeetCode) 普通版本(二维矩阵的直接读写) 解决办法:直接依据题目要求新建并填写一个二维数组,最后再将该二维数组中的有效字符按从左到右、从上到下的顺序读取并…...
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 算法详解
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 | 接辅导、项目定制 文本的输入处理中,transformer会将输入文本序列的每个词转化为一个词向量,我们通常会选择一个合适的长度作为输入…...
谷神前端组件增强:自定义列
初始化 $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驱动程序中,事件标记组(Event Group)是一个非常重要的概念。它是FreeRTOS中的一种同步机制,用于在任务之间传递和同步事件。在WiFi驱动程序中,我们使用事件标记组来通…...
构建企业级AI私有知识库
一、引言 在当今竞争激烈的市场环境中,企业为了保持竞争优势,需要高效地管理和利用内部知识资源。构建一个企业级AI私有知识库,不仅可以集中存储和管理企业知识,还能通过人工智能技术实现知识的智能化处理和利用。本文将详细介绍…...
C语言王国——杨氏矩阵
目录 1. 引言 2. 了解杨氏矩阵 3. 思路分析 4. 代码 5. 总结 1. 引言 最近在做二维数组的训练的时候发现了一个很有意思的题: 一看这不是杨氏矩阵嘛,接下来就由姜糖我带大家了解一下这个著名的矩阵。 2. 了解杨氏矩阵 通过查阅百度得知: …...
陪玩小程序都需要怎么做?
开发陪玩小程序需要进行全面的需求分析、功能规划、技术选型、界面设计等一系列步骤。陪玩小程序作为一种新兴的网络服务平台,为用户提供了寻找游戏伙伴、预约陪玩服务等功能,满足了用户在游戏领域的社交互动和技能提升需求。具体分析如下: 需…...
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…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
