一、

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和串行化的更多相关文章

  1. Lua文件操作和串行化

    function n_serialize(data) if type(data)=="number" then io.write(data,"\n") else ...

  2. MFC用串行化实现文档存储和读取功能

    在面向对象的程序设计中,一般都是用二进制文件来保存文档资料.在VC++中控制和使用文件流的方法很多,MFC程序设计中常用的有两种方法:用CFile对象存储和读取文件:利用串行化存取文件.其中用CFil ...

  3. MFC【6】文件I/O和串行化

    文件输入和输出(I/O)服务是所有操作系统的主要工作.Microsoft Windows提供了各种API函数用来读.写和操作磁盘文件.MFC将这些桉树和CFile类融合在面对对象的模型里.其中CFil ...

  4. MFC 文件I/O和串行化

    1.枚举所有文件夹(递归) void EnumerateFolders () { WIN32_FIND_DATA fd; HANDLE hFind = ::FindFirstFile (_T (&qu ...

  5. MFC如何生成一个可串行化的类

    一.MFC允许对象在程序运行的整个过程中持久化的串行化机制 (1)串行化是指向持久化存储媒介(如一个磁盘文件)读或写对象的过程. (2)串行化用于在程序运行过程时或之后修复结构化数据(如C++类或结构 ...

  6. VC++ MFC如何生成一个可串行化的类

    一.MFC允许对象在程序运行的整个过程中持久化的串行化机制(1)串行化是指向持久化存储媒介(如一个磁盘文件)读或写对象的过程.(2)串行化用于在程序运行过程时或之后修复结构化数据(如C++类或结构)的 ...

  7. MFC六大核心机制之四:永久保存(串行化)

    永久保存(串行化)是MFC的重要内容,可以用一句简明直白的话来形容其重要性:弄懂它以后,你就越来越像个程序员了! 如果我们的程序不需要永久保存,那几乎可以肯定是一个小玩儿.那怕我们的记事本.画图等小程 ...

  8. Java 对象的串行化(Serialization)

    1.什么是串行化 对象的寿命通常随着生成该对象的程序的终止而终止.有时候,可能需要将对象的状态保存下来,在需要时再将对象恢复.我们把对象的这种能记录自己的状态以便将来再生的能力.叫作对象的持续性(pe ...

  9. QDataStream类参考(串行化数据,可设置低位高位,以及版本号),还有一个例子

    QDataStream类提供了二进制数据到QIODevice的串行化. #include 所 有成员函数的列表. 公有成员 QDataStream () QDataStream ( QIODevice ...

随机推荐

  1. 6.HTML+CSS制作一双眼睛

    效果地址:https://codepen.io/flyingliao/pen/oOLodJ?editors=1100 其它动画效果地址:1.https://scrimba.com/c/cJ8NPpU2 ...

  2. idea搭spring boot项目

    Spring Boot是由Pivotal团队提供的全新框架,设计目的是用来简化新Spring应用的初始搭建以及开发过程.它主要推崇的是'消灭配置’,实现零配置. 那么,如何在idea中创建一个spri ...

  3. leetcode55

    bool canJump(vector<int>& nums) { ]; ; i < nums.size() && reach >= i; i++) { ...

  4. This iPhone 6s is running iOS 11.3.1 (15E302), which may not be supported by this version of Xcode.

    This iPhone 6s is running iOS 11.3.1 (15E302), which may not be supported by this version of Xcode.

  5. 26.Hibernate-主键和映射.md

    目录 1.复合主键映射 [toc] 2.集合映射 2.1Set集合 2.2其他集合 [toc] 3.集合数据的读取 [toc] 4.一对多和多对一映射 4.1概念 4.2配置和开发 4.2.1关键点 ...

  6. 解决 jdk8 Illegal key size or default parameters 错误

    网上搜到的答案如:https://blog.csdn.net/educast/article/details/81060085  大多是jdk1.6或1.7版本,有的jdk是1.8.99之前的版本,而 ...

  7. spark快速开发之scala基础之5高阶函数,偏函数,闭包

    高阶函数 高阶函数就是将函数作为参数或者返回值的函数. object function { def main(args: Array[String]): Unit = { println(test(f ...

  8. 《CSAPP》符号和符号表

    符号和符号表 每个可重定位目标模块m都有一个符号表,它包含m所定义和引用的符号的信息. 有三种不同的符号: 由m定义并能被其他模块引用的全局符号.对应非静态的C函数以及不带C static属性的全局变 ...

  9. 【前言】Go语言开坑

    很早之前就已经听过Go语言的大名,今天终于要开坑研究Go了,来吧看看<Go语言从入门到入坟>. [Go语言学习目录] 1. Go安装 2. Go变量(Variables) 3. Go语言基 ...

  10. cobbler的ks文件带有特殊字符导致错误

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAykAAACWAQMAAADg0FUUAAAAAXNSR0IArs4c6QAAAAZQTFRFq6urAA