MFC文件IO和串行化
一、
MFC中CFile对象实现了磁盘文档的读写,但是大部分MFC应用程序的IO服务都使用CArchive对象来完成。不管CFile和Archive输入输出的都是二进制数据,非文本数据。
int a = 0;
CFile file(TEXT("log.txt"), CFile::modeCreate | CFile::modeReadWrite | CFile::modeNoTruncate);
file.Write(&a, sizeof(a));
CArchive ar(&file, CArchive::store);
ar << a ;
上面两种输出方式得到的结果同。
二、
MFC重载了<<和>>运算符,以便能够串行或并行化MFC中的基本数据类型和一些MFC中的非基本数据类型,比如CString。
同时,MFC还允许用户能够创建自己的可串行化类,使它们能够与CArchive的插入提取运算符一起工作。
下面介绍如何编写一个可串行化类:
1.直接或者间接的CObject的派生类。
2.在类的声明中写入MFC的DECLEAR_SERIAL宏,改宏只接收一个参数:类名。
3.重载父类中的Serialize函数,在该函数中串行化派生类的数据成员。
4.如果派生类没有默认构造函数,则需要添加一个。对象并行化时,MFC使用默认构造函数创建对象,并未数据成员赋值。
5.在类的实现中写入MFC的IMPLEMENT_SERIAL宏,该宏接受三个参数:类名,基本类名和模式号。模式号等价于版本号,只要
修改了类的串行化数据格式,模式号也要随之改变。
具体实现如下:
类声明:
class CLine :public CObject
{
public:
DECLARE_SERIAL(CLine);
CLine();
CLine(CPoint from, CPoint to){ m_ptFrom = from; m_ptTo = to; }
virtual void Serialize(CArchive& ar);
~CLine();
protected:
CPoint m_ptFrom;
CPoint m_ptTo;
};
类定义:
IMPLEMENT_SERIAL(CLine, CObject, 1)
void CLine::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
ar << m_ptFrom << m_ptTo;
}
else
{
ar >> m_ptFrom >> m_ptTo;
}
}
三、
如果后续开发过程中,CLine添加了一个持久性数据成员,则需要把版本号增加到2,这样就能够根据不同版本区别串行化到磁盘的CLine对象。
否则,磁盘版本为1的CLine就可能被读入内存版本为2的CLine中。
如何让程序向下兼容既能够读取版本号为1的磁盘上的数据又能够读取版本号为2的磁盘上的数据呢?
可是化模式也就诞生了,可视化模式只是包含VERSIONABLE_SCHEMA标志的模式号,该标志禁止产生CArichiveException,并允许应用程序对不同的模式号
有判断地响应。使用了可视化模式可以给用户提供向下兼容性。
编写一个具有MFC可视化模式支持的可串行化类,一般需要两步:
1. 将IMPLEMENT_SERIAL宏中的模式号与宏VERSIONABLE_SCHEMA相或。
2. 如果从archive加载对象时,需要调用CArchive::GetObjectSchema,该函数返回并行化对象的模式号,同时还需要修改Serialize函数。
具体实现如下
类声明中:
class CLine :public CObject
{
public:
DECLARE_SERIAL(CLine);
CLine();
CLine(CPoint from, CPoint to){ m_ptFrom = from; m_ptTo = to; }
virtual void Serialize(CArchive& ar);
~CLine();
protected:
CPoint m_ptFrom;
CPoint m_ptTo;
COLORREF m_clrLine;
};
类实现中:
IMPLEMENT_SERIAL(CLine, CObject, 2|VERSIONABLE_SCHEMA)
void CLine::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
ar << m_ptFrom << m_ptTo << m_clrLine;
}
else
{
UINT sechema = ar.GetObjectSchema();
switch (sechema)
{
case 1:
ar >> m_ptFrom >> m_ptTo;
m_clrLine = RGB(0, 0, 0);
break;
case 2:
ar >> m_ptFrom >> m_ptTo >> m_clrLine;
break;
default: break;
}
}
}
四、
最后,MFC为CObject指针重载了<< 和 >>符号,但是CObject对象没有重载,所以我们在对一个对象进行串行化时可以直接调用它的Serialize函数,
但是,这样的串行化后的对象将没有版本号。
MFC文件IO和串行化的更多相关文章
- Lua文件操作和串行化
function n_serialize(data) if type(data)=="number" then io.write(data,"\n") else ...
- MFC用串行化实现文档存储和读取功能
在面向对象的程序设计中,一般都是用二进制文件来保存文档资料.在VC++中控制和使用文件流的方法很多,MFC程序设计中常用的有两种方法:用CFile对象存储和读取文件:利用串行化存取文件.其中用CFil ...
- MFC【6】文件I/O和串行化
文件输入和输出(I/O)服务是所有操作系统的主要工作.Microsoft Windows提供了各种API函数用来读.写和操作磁盘文件.MFC将这些桉树和CFile类融合在面对对象的模型里.其中CFil ...
- MFC 文件I/O和串行化
1.枚举所有文件夹(递归) void EnumerateFolders () { WIN32_FIND_DATA fd; HANDLE hFind = ::FindFirstFile (_T (&qu ...
- MFC如何生成一个可串行化的类
一.MFC允许对象在程序运行的整个过程中持久化的串行化机制 (1)串行化是指向持久化存储媒介(如一个磁盘文件)读或写对象的过程. (2)串行化用于在程序运行过程时或之后修复结构化数据(如C++类或结构 ...
- VC++ MFC如何生成一个可串行化的类
一.MFC允许对象在程序运行的整个过程中持久化的串行化机制(1)串行化是指向持久化存储媒介(如一个磁盘文件)读或写对象的过程.(2)串行化用于在程序运行过程时或之后修复结构化数据(如C++类或结构)的 ...
- MFC六大核心机制之四:永久保存(串行化)
永久保存(串行化)是MFC的重要内容,可以用一句简明直白的话来形容其重要性:弄懂它以后,你就越来越像个程序员了! 如果我们的程序不需要永久保存,那几乎可以肯定是一个小玩儿.那怕我们的记事本.画图等小程 ...
- Java 对象的串行化(Serialization)
1.什么是串行化 对象的寿命通常随着生成该对象的程序的终止而终止.有时候,可能需要将对象的状态保存下来,在需要时再将对象恢复.我们把对象的这种能记录自己的状态以便将来再生的能力.叫作对象的持续性(pe ...
- QDataStream类参考(串行化数据,可设置低位高位,以及版本号),还有一个例子
QDataStream类提供了二进制数据到QIODevice的串行化. #include 所 有成员函数的列表. 公有成员 QDataStream () QDataStream ( QIODevice ...
随机推荐
- LeetCode contest-95[876,877,👁878]
876. Middle of the Linked List first submission # Definition for singly-linked list. # class ListNod ...
- 在BootStrap的modal中使用Select2搜索框无法输入
用modal来show一个对话框 dialog.modal({ backdrop:true, keyboard:true, show:true }); 1 2 3 4 5 然后再modal中初始化se ...
- js day03
一)jQuery常用AJAX-API 目的:简化客户端与服务端进行局部刷新的异步通讯 (1)取得服务端当前时间 简单形式:jQuery对象.load(url) 返回结果自动添加到jQuery对象代表的 ...
- SpringMVC Get请求传集合,前端"异步"下载excel 附SpringMVC 后台接受集合
最近项目上管理后台需要自己做一部分js部分,之前都是前端来弄...碰到了下载excel,刚开始使用ajax,搞了好久发现不合适..下载不了,网上说ajax返回类型不支持二进制流.. 因此采用 wind ...
- 请求不同域的数据方法:requests Jsonp cors
在需要访问不同域的接口的数据的时候,一般有两种方式: 第一种: 使用requests模块,在业务逻辑中直接访问别的域的接口,获取数据,然后将返回的数据显示到前端页面上; 这个时候,数据访问的流程是: ...
- (转)SQL SERVER 生成建表脚本
https://www.cnblogs.com/champaign/p/3492510.html /****** Object: StoredProcedure [dbo].[GET_TableScr ...
- 【Django】django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.
最近学习Django的过程中,在cmd打算使用python manage.py shell来测试数据的时候,当我一导入自己写的model类,就发现报了这个错误django.core.exception ...
- Jenkins之定时任务
H的用法: H 10 * * * ,这里H不是小时的意思,符号H(代表“Hash”,后面用“散列”代替) 符号H 在一定范围内可被认为是一个随机值,但实际上它是任务名称的一个散列而不是随机函数,每个 ...
- cmd中sudo以后显示password不能输入密码
文本界面还是图形界面下输入密码都不会有回显,这是为了安全考虑. 其实你不是不能输入密码只是你看不到而已,事实上你已经输入进去了,回车后就能看到效果了. 来源于:https://zhidao.baidu ...
- JAVA中float与double的区别
float是单精度类型,精度是8位有效数字,取值范围是10的-38次方到10的38次方,float占用4个字节的存储空间 double是双精度类型,精度是17位有效数字,取值范围是10的-308次方到 ...