MFC用串行化实现文档存储和读取功能
在面向对象的程序设计中,一般都是用二进制文件来保存文档资料。在VC++中控制和使用文件流的方法很多,MFC程序设计中常用的有两种方法:用CFile对象存储和读取文件;利用串行化存取文件。其中用CFile对象直接存储文档,存在着以下两个问题:一是过程繁琐,例如绘图系统中常存在大量的数据对象(直线对象、矩形对象等);另一个问题是功能受限,VC++为了程序集成的需要,设汁成了复合文档,可以把各种外来对象(如OLE对象的嵌入和链接)的内容存储到外部文件中并从外部文件中读取内容更新构造对象,而程序的设计者并不知道这些对象中需要存储数据的内容和格式,在这种情况下,直接利用CFile类就无能为力了。
既然已决定采用串行化的方法,就要明确串行化的概念:CArchive类用于以持久的二进制形式(通常是磁盘存储)来存储一个复杂的对象网络,用户可以把对象的内容存储到存储区中,也可以从存储区中读取内容重新构造对象。这个过程成为“串行化”,下面介绍串行化的几个基础知识点:
1 CArchive。
构造函数:CArchive( CFile* pFile, UINT nMode, int nBufSize = 4096, void* lpBuf = NULL ),参数意义查阅MSDN。两个重要函数:IsStoring()和IsLoading(),以及>>和<<两个重载的操作符。
2 如何使自定义的类具有串行化功能呢?有以下五个步骤:
1)Deriving your class from CObject (or from some class derived from CObject).
2)Overriding the Serialize member function.
3)Using the DECLARE_SERIAL macro in the class declaration.
4)Defining a constructor that takes no arguments.
5)Using the IMPLEMENT_SERIAL macro in the implementation file for your class.
3 CObArray::Serialize()。CObArray类支持CObject类对象指针数组,它如同一个指针数组来管理直接或间接派生的CObject对象指针。当调用一个CObArray对象的Serialize()函数进行存储操作时,首先存储了数组的项数,然后循环对各个项目(各个对象)进行存储,进行了如下操作:
1)将对象的信息写入文件。包括类的信息;版本信息;
2)调用对象的Serialize成员函数,将对象的数据写入文件。
而当进行读取操作时,首先读取了存储数组的项目数,然后将数组的项目初始化成需要的项目数,然后进行如下操作:
1)从文件读取类的信息,动态生成相应类(CLine)的对象,存放对象的指针;
2)调用对象的Serialize()成员函数,从文件读取对象数据初始化新生成的对象。
4 Document/View结构
1)在MFC中,文档类负责管理数据,提供保存和加载数据的功能。视类负责数据的显示,以及给用户提供对数据的编辑和修改功能。
2)MFC给我们提供Document/View结构,将一个应用程序所需要的“数据处理与显示”的函数空壳都设计好了,这些函数都是虚函数我们可以在派生类中重写这些函数。有关文件读写的操作在CDocument的Serialize函数中进行,有关数据和图形显示的操作在CViewOnDraw函数中进行。我们在其派生类中,只需要去关注Serialize和OnDraw函数就可以了,其它的细节我们不需要去理会,程序就可以良好地运行。
3)当我们按下“File/Open”,Application Framework会激活文件打开对话框,让你指定文件名,然后自动调CGraphicDoc::Serialize读取文件。Application Framework还会调用CGraphicView::OnDraw,传递一个显示DC,让你重新绘制窗口内容。MFC给我们提供Document/View结构,是希望我们将精力放在数据结构的设计和数据显示的操作上,而不要把时间和精力花费在对象与对象之间、模块与模块之间的通信上。
4)一个文档对象可以和多个视类对象相关联,而一个视类对象只能和一个文档对象相关联。
5 String Table中IDR_MAINFRAME字符串资源中各子串的含义
1)CDocTemplate::windowTitle,主窗口标题栏上的字符串,MDI程序不需要指定,将以IDR_MAINFRAME字符串为默认值。
2)CDocTemplate::docName,缺省文档的名称。如果没有指定,缺省文档的名称是无标题。
3)CDocTemplate::fileNewName,文档类型的名称。如果应用程序支持多种类型的文档,此字符串将显示在"File/New"对话框中。如果没有指定,就不能够在"File/New"对话框处理这种文件。
4)CDocTemplate::filterName,文档类型的描述和一个适用于此类型的通配符过滤器。这个字符串将出现在“File/Open”对话框中的文件类型列表框中。要和CDocTemplate::filterExt一起使用。
5)CDocTemplate::filterExt,文档的扩展名。如果没有指定,就不能够在“File/Open”对话框中处理这种文档。要和CDocTemplate::filterName一起使用。
6)CDocTemplate::regFileTypeId,如果你以::RegisterShellFileTypes向系统的注册表注册文件类型,此值会出现在HEY_CLASSES_ROOT之下成为其子项,并仅供Windows内部使用。如果没有指定,这种文件类型就无法注册。
7)CDocTemplate::regFileTypeName,这也是存储在注册表中的文件类型名称。它会显示于程序中用以访问注册表的对话框内。
下面介绍用串行化实现文档存储与读写的步骤:
1 实现一个可串行化的类(五个步骤)。特别注意的是改写Serialize()函数;
2 修改String Table中IDR_MAINFRAME字符串资源中子串,使其符合自己需求;
3 在CMyDoc类中增加一个CObArray的成员变量;修改CMyDoc::Serialize();如果需要保存CMyView类中的数据成员,可以利用一下代码获取CMyView的指针:POSITION pos=GetFirstViewPosition(); CGraphicView *pView=(CGraphicView*)GetNextView(pos);
4 新建和打开文档时,要注意销毁原来的数据。在DOC的DeleteContents虚函数中是好时机。代码如下:
- int nCount;
- nCount=m_obArray.GetSize();
- for(int i=0;i<nCount;i++)
- {
- delete m_obArray.GetAt(i);//释放指针指向的内存空间
- //m_obArray.RemoveAt(i);//移除链表中的元素。嘿嘿,别搞错了。但在此处不能这样用,会导致非法操作。要用下面的方法
- }
- Array.RemoveAll();
还有一种方法:
- while(nCount--)
- {
- delete m_obArray.GetAt(nCount);
- m_obArray.RemoveAt(nCount);
- }
MFC用串行化实现文档存储和读取功能的更多相关文章
- MFC如何生成一个可串行化的类
一.MFC允许对象在程序运行的整个过程中持久化的串行化机制 (1)串行化是指向持久化存储媒介(如一个磁盘文件)读或写对象的过程. (2)串行化用于在程序运行过程时或之后修复结构化数据(如C++类或结构 ...
- VC++ MFC如何生成一个可串行化的类
一.MFC允许对象在程序运行的整个过程中持久化的串行化机制(1)串行化是指向持久化存储媒介(如一个磁盘文件)读或写对象的过程.(2)串行化用于在程序运行过程时或之后修复结构化数据(如C++类或结构)的 ...
- 关于ORACLE的串行化隔离级别--来自ORACLE概念手册
为了描述同时执行的多个事务如何实现数据一致性,数据库研究人员定义了被 称为串行化处理(serializability)的事务隔离模型(transaction isolation model).当所有 ...
- VC++ chap13 文档与串行化
Lesson 13 文档与串行化 13.1使用CArchive类对文件进行读写操作 //让对象数据持久性的过程称之为串行化,或者序列化 void CGraphicView::OnFileWrite() ...
- MFC文件IO和串行化
一. MFC中CFile对象实现了磁盘文档的读写,但是大部分MFC应用程序的IO服务都使用CArchive对象来完成.不管CFile和Archive输入输出的都是二进制数据,非文本数据. int a ...
- MFC六大核心机制之四:永久保存(串行化)
永久保存(串行化)是MFC的重要内容,可以用一句简明直白的话来形容其重要性:弄懂它以后,你就越来越像个程序员了! 如果我们的程序不需要永久保存,那几乎可以肯定是一个小玩儿.那怕我们的记事本.画图等小程 ...
- 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 ...
- QDataStream类参考(串行化数据,可设置低位高位,以及版本号),还有一个例子
QDataStream类提供了二进制数据到QIODevice的串行化. #include 所 有成员函数的列表. 公有成员 QDataStream () QDataStream ( QIODevice ...
随机推荐
- 大规模Elasticsearch集群管理心得
转载:http://elasticsearch.cn/article/110 ElasticSearch目前在互联网公司主要用于两种应用场景,其一是用于构建业务的搜索功能模块且多是垂直领域的搜索,数据 ...
- 关于virgo-tomcat-server-3.6.0.RELEASE配置文件修改说明
Virgo项目Web服务器是EclipseRT项目的一部分,是一个完全模块化的Java运行时. Virgo自身就是设计为在标准OSGi框架实现(Equinox)之上的一个OSGi bundle集合. ...
- 【BZOJ2331】[SCOI2011]地板 插头DP
[BZOJ2331][SCOI2011]地板 Description lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西.小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里 ...
- 云存储命令行工具---libs3
ceph 的客户端有很多,有s3cmd.cloudberryExplorer等,今天介绍另一个libs3 一. 安装 Libs3是RGW s3接口的命令行工具,与s3cmd类似,使用C++生成. 1. ...
- jmeter聚合报告导出时乱码的解决
在使用jmeter性能测试时,聚合报告导出后使用excel打开时是乱码,查看相关文件后是编码的问题,解决方法如下: 1.现象: 用excel打开变成这种乱码无法看清 2.解决: 先使用记事本打开后,选 ...
- Spark2 Dataset聚合操作
data.groupBy("gender").agg(count($"age"),max($"age").as("maxAge&q ...
- 7.20python线程(2)
RLock 递归锁 线程事件
- sublime text3控制台每次报错会显示几行[ ]
如下图所示,每次编译报错的时候会显示: 我只需要报错信息,不想红框中的信息出现. 解决方案: 1 找到sublime Text3安装路径下的Default.sublime-package,如~Subl ...
- 【python-opencv】对象测量
opencv 中轮廓特征包括: 如面积,周长,质心,边界框等 *弧长与面积测量 *多边形拟合 *获取轮廓的多边形拟合结果 python-opencv API提供方法: cv2.moments()用来计 ...
- Python实现常用的逻辑数据结构
逻辑数据结构包括:线形结构.树形结构.图形结构.集合:存储结构包括:顺序存储.链式存储.索引存储.散列存储. 同一种逻辑结构可以有四种存储结构,不同的存储结构增.删.查.改的速度不同.逻辑结构与存储结 ...