MFC界面编程基础(17):文档序列化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_17017545/article/details/85231269
上一篇:MFC界面编程基础(16):文档、视图、框架 下一篇:MFC界面编程基础(18):文档视图结构应用程序例子(Ex_DocView)

序列化定义

MFC文档-视图结构中,序列化机制可以实现内存中对象储存和加载
序列化机制分为序列化和反序列化:

  • 序列化是把内存中的对象以二进制文件的形式存储在磁盘中
  • 反序列化是把序列化后生成的文件恢复到内存。

CArchive类

CArchive没有基类。CArchive允许以一个永久二进制(通常为磁盘存储)的形式保存一个对象的复杂网络,它可以在对象被删除时,还能永久保存。可以从永久存储中装载对象,在内存中重新构造它们。使得数据永久保留的过程就叫作 “序列化”。
可以把一个归档对象(CArchive)看作一种二进制流。像输入/输出流一样,归档与文件有关并允许写缓冲区以及从硬盘读出或读入数据。输入/输出流处理一系列ASCII字符,但是归档文件以一种有效率、精练的格式处理二进制对象

CArchive对象处理基础类型数据

必须在创建一个CArchive对象之前,创建一个CFile对象。另外,必须确信归档文件的装入/存储与文件的打开模式是兼容的。每一个文件只限于一个活动归档文件。当构造一个CArchive对象时,要把它附加给表示一个打开文件的类CFile(或派生类)的对象上。还要指定归档文件将用于装载还是存储。

  • 示例:
//将数据以二进制方式写入文件中
void CArchiveView::OnWritefile()
{
	// TODO:  在此添加命令处理程序代码
	//构造CFile文件对象
	CFile file(_T("demo.txt"), 
CFile::modeCreate | CFile::modeWrite);
	//构造存档对象
	CArchive ar(&file, CArchive::store);
	int a = 12;
	char ch = 'p';
	double b = 12.345;
	CString str = _T("大江东去浪淘尽, 千古风流人物");
	//保存数据
	ar << a << ch << b << str;
}
//从文件中读取数据
void CArchiveView::OnReadfile()
{
	// TODO:  在此添加命令处理程序代码
	//构造CFile文件对象
	CFile file(_T("demo.txt"), CFile::modeRead);
	//构造存档对象
	CArchive ar(&file, CArchive::load);
	//定义变量,存放加载出来的数据
	int a;
	char ch;
	double b;
	CString str;
	//加载数据
	ar >> a >> ch >>b >> str;
	//格式化字符串
	CString strResult;
	strResult.Format(_T("%d\n%c\n%lf\n%s"), a, ch, b, str);
	MessageBox(strResult);
}

CArchive对象处理自定义对象类型数据

CArchive对象不仅可以处理基础类型,而且还能处理为序列化而设计的特殊的类的对象。可以序列化的类有以下特点

  • 必须为CObject派生类。直接或者间接的继承CObject类;
  • 必须重写CObject类的Serialize成员函数;
  • 使用DECLARE_SERIAL和IMPLEMENT_SERIAL宏;
  • 必须有一个默认构造函数。

在Serialize成员函数中完成保存和加载的功能。

DECLARE_SERIAL( class_name ) 参数为当前类名。
IMPLEMENT_SERIAL( class_name, base_class_name, wSchema ) 
  • 第一个参数为当前类名
  • 第二个参数为父类类名
  • 第三个参数为该类的特定整型标识,该标识将用来解序(重新实例化),最小为0。

示例:

DrawBase.h
//////////////////////////////////////////////////////
class CDrawBase : public CObject //继承自CObject
{
public:
    DECLARE_SERIAL(CDrawBase)    //第一个宏的位置,参数为当前类名
    CDrawBase();					//必须有一个默认构造函数
    virtual void onDraw(CDC* pdc);
    virtual ~CDrawBase();
public:
    UINT m_PenStyle;
    int m_PenWidth;
    int m_BkMode;
    int m_BrushStyle;
    int m_issx;
    int m_isyy;
    COLORREF m_PenColor;
    COLORREF m_BackgroundColor;
    COLORREF m_BrushColor;
    CPoint m_ptBegin;
    CPoint m_ptEnd;
public:
    void Serialize(CArchive& ar);		//重写了Serialize成员函数
};
//////////////////////////////////////////////////////
DrawBase.cpp
//////////////////////////////////////////////////////
//第二个宏的位置,第一个参数为当前类名,第二个参数为父类类名,
//第三个参数为该类的特定整型标识,该标识将用来解序(重新实例化),
//最小为0
IMPLEMENT_SERIAL(CDrawBase, CObject, 1)
void CDrawBase::Serialize(CArchive& ar)
{
    CObject::Serialize(ar);
    if(ar.IsStoring())		//保存,加载为ar.IsLoading()
    {
        ar <<m_PenColor<<m_PenStyle<<m_PenWidth
<<m_BrushColor<<m_BrushStyle<<m_issx<<m_isyy;
    }
    else 	//加载
    {
    		ar >>m_PenColor>>m_PenStyle>>m_PenWidth>>
m_BrushColor>>m_BrushStyle>>m_issx>>m_isyy;
    }
}

总结

重载提取(>>)和插入(<<)是方便的归档编程接口。它支持主要类型和CObject派生类。
CArchive还支持使用MFC Windows套接字类CSocket和CSocketFile编程。IsBufferEmpty成员函数也支持这种使用。一些集合类也支持序列化,CObArray,Vector,CPtrArray。
在MFC文档-视图结构中,Doc类是被系统设定好支持序列化的类,在Doc类中重写Serialize成员函数。在函数中对你要保存的对象序列化。完成之后,点击菜单栏上的保存和打开就可以实现序列化了。

上一篇:MFC界面编程基础(16):文档、视图、框架 下一篇:MFC界面编程基础(18):文档视图结构应用程序例子(Ex_DocView)

猜你喜欢

转载自blog.csdn.net/qq_17017545/article/details/85231269
今日推荐