MFC编程案例chapter013.pdf
《MFC编程案例chapter013.pdf》由会员分享,可在线阅读,更多相关《MFC编程案例chapter013.pdf(38页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、下载第13章 文件、串行化和数据库本章的例子涉及从简单二进制文件到访问第三方的数据库管理系统等方面的内容。文件串行化的概念是M F C特有的,串行化允许你组织如何保存类对象到磁盘上,以便以较小的代价检索甚至升级它们。串行化从 a r c h i v e文件中保存或调出,a r c h i v e文件其实是一个二进制文件。例63 访问二进制文件讨论用M F C类访问和操作一个简单的二进制文件。例64 访问标准I/O文件讨论用M F C类访问文本文件。例65 访问内存文件讨论创建和操作内存中的二进制文件。尤其是,内存文件可以使你利用文件系统的方法来访问堆内存的单元。例66 在数据类中实现串行化在数
2、据类中加入串行化功能。在本例中不实际串行化任何东西这些留到下五个例子来做。例67 串行化S D I或M D I文档利用M F C的内置功能自动串行化数据类。例68 按要求串行化按要求串行化一个或多个数据类,而不仅仅是保存和装入一个文档。例69 透明地更新串行化的文档讨论怎样如何通过简单地修改新数据类,以转化旧数据,使新数据类仍然能使用旧的串行化文档。例70 串行化多态类串行化一组数据类,这些类的唯一共同点是它们派生于同一个基类。例71 串行化数据集讨论M F C集类内置的串行化功能。例72 访问O D B C数据库讨论怎样使用M F C类访问一个满足O D B C协议的数据库。例73 访问D
3、A O数据库讨论怎样使用M F C类访问一个满足D A O协议的数据库。13.1 例63 访问二进制文件目标在一个平面磁盘文件中维护二进制数据。策略利用M F C的C F i l e类,该类封装了Windows API中处理二进制文件的函数。步骤1.检查文件是否存在要判断某个文件是否已在磁盘上存在,可以使用静态 C F i l e函数GetStatus()。CFileStatus status;if(!CFile:GetStatus(sFile,status)msg.Format(%s does not exist,sFile);A f x M e s s a g e B o x(m s g)
4、;2.创建一个二进制文件为了创建一个可写的二进制文件,首先创建一个 C F i l e类对象,然后利用Open()成员函数打开并创建一个文件对象。CFile file;CString msg;CString sFile(Wzd.tmp);if(!file.Open(sFile,CFile:modeCreate|CFile:modeWr i t e)msg.Format(Failed to create%s.,sFile);A f x M e s s a g e B o x(m s g);3.使用二进制文件1)写二进制数据到文件中。f i l e.Write(buff e r,sizeof(bu
5、ff e r);2)关闭文件,销毁文件对象。file.Close();3)打开一个二进制文件进行读操作。if(!file.Open(sFile,CFile:modeRead)msg.Format(Failed to open%s.,sFile);A f x M e s s a g e B o x(m s g);4)获得二进制或其他类型文件的长度。UINT nBytes=file.GetLength();5)使用如下函数之一以改变文件读写的当前位置。f i l e.S e e k To E n d();file.Seek(20,/file offset in bytesCFile:begin);
6、/also CFile:end and CFile:currentf i l e.S e e k To B e g i n();6)利用如下代码从二进制文件中读取数据,其中 n B y t e s是实际读取的字节数。若 n B y t e s比想要读取的字节数小或者为0,则已到文件结束处。nBytes=file.Read(buff e r,sizeof(buff e r);7)设置文件为只读,使用 C F i l e的静态成员函数SetStatus()。本例中,我们获取文件当前的任何状态,并加上只读状态标记。if(CFile:GetStatus(sFile,status)s t a t u s
7、.m _ a t t r i b u t e|=0 x 0 1;CFile:SetStatus(sFile,status);8)删除一个文件,使用C F i l e的另外一个静态函数Remove()。CFile:Remove(sFile);226第三部分 内部处理实例下载说明C+类中,C F i l e和大多数其他M F C类一样包含了许多一个 C+类中的Windows API调用。C W n d类对于窗口是这样,C M e n u类对于菜单也是这样。关于操作文本文件参见下一个例子。CD说明在C D上执行该工程时,在 W z d Vi e w.c p p的O n TestWzd()函数处设置断
8、点。选取菜单上的Te s t/W z d项,一步步地观察二进制文件的访问。13.2 例64 访问标准I/O文件目标操作文本文件。策略利用M F C的C S t d i o F i l e类操作文本文件。C S t d i o F i l e从C F i l e类派生,并封装Windows API中用来处理文本文件的函数。步骤1.检查一个文件是否存在使用C F i l e类的GetStatus()静态函数,判断一个文本文件是否存在。CFileStatus status;CString sFile(Wzd.txt);if(!CFile:GetStatus(sFile,status)msg.Form
9、at(%s does not exist,sFile);A f x M e s s a g e B o x(m s g);2.创建一个文本文件打开一个文本文件以写文本串。本例中,若所找文件无法打开,则创建一个新文件。CStdioFile file;if(!file.Open(sFile,CFile:modeWrite|CFile:typeTe x t)if(!file.Open(sFile,CFile:modeCreate|C F i l e:m o d e Write|CFile:typeTe x t)CString msg;msg.Format(Failed to create%s.,sF
10、ile);3.使用文本文件1)写一个文本串到文件中。第13章 文件、串行化和数据库227下载f i l e.WriteString(sRecord);2)关闭文件并销毁创建的文件对象。file.Close();3)打开一个文本文件进行读操作。if(!file.Open(sFile,CFile:modeRead|CFile:typeTe x t)msg.Format(Failed to open%s.,sFile);A f x M e s s a g e B o x(m s g);4)定位到文件的头和尾。f i l e.S e e k ToEnd();f i l e.S e e k ToBegi
11、n();5)从一个文本文件中读一个文本串。file.ReadString(sRecord);6)删除一个文本文件。CFile:Remove(sFile);说明与二进制文件以同样方式对待每个字节所不同的是,标准 I/O文件使用fgets()和fputs()函数获取和输入文本串到文件中。既然C S t d i o F i l e是从CFi l e派生的,在C F i l e中可用的函数在此都可用。CD说明在C D上执行该工程时,在 W z d Vi e w.c p p中的函数O n TestWzd()处设置断点。选取菜单上的Te s t/W z d项,一步步观看标准I/O文件的访问。13.3 例6
12、5 访问内存文件目标在内存中生成一个文件,而不是在磁盘上生成一个临时文件。策略使用M F C的C M e m F i l e类,该类是从C F i l e类派生的,封装分配内存的Windows API。步骤1.创建一个内存文件要创始一个内存文件,只要创建一个 C M e m F i l e类对象。CMemFile file;创建一个C M e m F i l e类对象自动打开一个内存文件。2.使用内存文件1)写内存文件。228第三部分 内部处理实例下载f i l e.Write(buff e r,sizeof(buff e r);2)判断内存文件的当前长度。UINT nBytes=file.G
13、etLength();3)使用以下方法定位下次读写的位置。f i l e.S e e k To E n d();file.Seek(20,/file offset in bytesCFile:begin);/also CFile:end and CFile:currentf i l e.S e e k To B e g i n();4)从内存文件中读数据。nBytes=file.Read(buff e r,sizeof(buff e r);5)删除内存文件有两种方法:一是销毁 C M e m F i l e类对象,二是设置文件长度为0。file.SetLength(0);说明内存文件为用户在内
14、存中操作数据提供了一种方便的途径,而不必考虑释放和分配堆空间的内存段。另外,内存文件可用作临时(.t m p)文件,这样可以加快应用程序的运行速度,同时没有命名和删除临时文件的麻烦。C M e m F i l e创建的内存文件是在应用程序的堆空间中生成的。若想在全局堆上创建内存文件,相应地要使用 C S h a r e d F i l e,特别是剪贴板要求其获取的数据必须在全局堆中。关于此问题的例子参见例7 6的剪切和粘贴。既然C M e m F i l e是从C F i l e而不是从C S t d i o F i l e派生来的,则必须实现 ReadString()和WriteString
15、()函数,以方便地操作内存文件中的文本数据。CD说明在C D上执行该工程时,在 W z d Vi e w.c p p中的O n TestWzd()函数上设置断点。单击菜单上的Te s t/W z d项,一步一步地观察内存文件的访问。13.4 例66 在数据类中实现串行化目标串行化数据类。策略实现从C O b j c t派生过来的数据类的串行化。M F C的C O b j e c t类添加一个虚重载函数到类中,该函数为Serialize()。我们将用我们自己的 Serialize()重载这个Serialize(),使之装入和保存成员变量到磁盘上。注意 本例中,数据类具有串行化自己的功能。实际如何
16、串行化类到磁盘上参见下例。步骤1.在数据类中加入Serialize()第13章 文件、串行化和数据库229下载从M F C的C O b j e c t派生得到用户的数据类。不是从 C O b j e c t派生的类不能进行串行化。因为C l a s s Wi z a r d没有提供把C O b j e c t作为类的基类的功能,则需要加进这个基类。class CMyData:public CObject;利用以下格式,在每个数据类中加入 Serialize()成员函数。void CWzdInfo2:Serialize(CArchive&ar)C O b j e c t:S e r i a l
17、i z e(a r);int version=1;i f(a r.I s S t o r i n g()/store datae l s e/load data现在可以利用Serialize()函数调出和保存每一个类的成员变量到存档设备中。如何串行化一个成员变量依赖于变量类型。有三种变量类型:不是从 C O b j e c t派生过来的简单变量,如integers,floats等;从C O b j e c t派生过来的变量;数据集,包括数组和列表。2.串行化简单变量1)要保存数据类中不是从C O b j e c t派生的成员变量,在 Serialize()函数的“保存数据”区使用 重载操作符。
18、C O b j e c t:S e r i a l i z e(a r);i f(a r.I s S t o r i n g()/store member variables not derived from CObjectar m_sName;ar 重载操作符。C O b j e c t:S e r i a l i z e(a r);i f(a r.I s S t o r i n g()/store datae l s e/load member variables not derived from CObjectar m_sName;ar m_sComment;3.串行化派生于C O b
19、j e c t的变量调用成员变量的Serialize()函数以保存派生于C O b j e c t的成员变量。/load and store member variables derived from CObject230第三部分 内部处理实例下载m _ w z d I n f o.S e r i a l i z e(a r);可以在类的Serialize()函数的调出和保存区中,调用该Serialize()函数,或者在if else 表达式之后调用该 Serialize()一次即可。若在变量类中没有实现 Serialize(),则应该加上一个。4.串行化数据集1)保存数据集,使用如下语句。n
20、Count=m_WzdInfoList.GetCount();/get number of/items inar S e r i a l i z e(a r);注意在这里我们首先保存数据集中工程的数目,然后一步一步地按顺序保存每个工程。2)使用如下语句,装入数据集。/load a list of dataar nCount;while(nCount-0)CWzdInfo2*pInfo=new CWzdInfo2;p I n f o-S e r i a l i z e(a r);m _ W z d I n f o L i s t.A d d Ta i l(p I n f o);关于数据类串行化的
21、详细清单,参见本节的“清单第一个数据类”和“清单第二个数据类”。说明串行化把数据类的每个成员变量按序列地存贮到磁盘上。调出或保存一个文档只不过是串行化上千个数据类而已。只要文档按它保存的顺序调出,就没有必要对文件进行其他控制。正如我们在后面例子看到一样,这种方法可以很快地把旧的文档格式“转化”为新的格式。关于串行化和C O b j e c t类的其他信息参见第2章。串行化的存档设备可以是磁盘文件、内存文件或甚至是别的系统上的文件。在例7 6中可以看到,串行化到内存文件可以为用户提供一种快速易用方式,来剪切和粘贴自己的数据类。一些M F C类可以使用 和 重载操作符来串行化其数据,但是这些类要自
22、己实现这种操作。如C S t r i n g就使用这个操作符。可以通过测试查看还有哪些 M F C类有这样的功能。把保存一个类对象并能在以后恢复它的能力叫做对象“存留”。CD说明本例子的工程称为“S e r i a l i z a t i o n”,开始时在W z d D o c.c p p中Serialize()上设置断点。然后第13章 文件、串行化和数据库231下载单击Te s t/W z d菜单命令填充文档,之后单击F i l e/S a v e开始串行化功能。清单第一个数据类#ifndef WZDINFO1_H#define WZDINFO1_H#include afxtempl.h#
23、include WzdInfo2.hclass CWzdInfo1:public CObjectp u b l i c:C W z d I n f o 1();C W z d I n f o 1();/misc infoCString m_sGroupName;CString m_sComment;CList m_WzdInfo2List;void Serialize(CArchive&archive);#e n d i f/WzdInfo1.cpp:implementation of the CWzdInfo class/#include stdafx.h#include WzdInfo1.
24、h/CWzdInfoC W z d I n f o 1:C W z d I n f o 1()m _ s G r o u p N a m e=_ T();m _ s C o m m e n t=_ T();C W z d I n f o 1:C W z d I n f o 1()while(!m_WzdInfo2List.IsEmpty()delete m_WzdInfo2List.RemoveHead();void CWzdInfo1:Serialize(CArchive&ar)232第三部分 内部处理实例下载C O b j e c t:S e r i a l i z e(a r);int
25、nCount;if(ar.I s S t o r i n g()/name and commentar m_sGroupName;ar m_sComment;/other listnCount=m_WzdInfo2List.GetCount();ar nCount;for(POSITION pos=m_WzdInfo2List.GetHeadPosition();pos;)CWzdInfo2*pInfo=m_WzdInfo2List.GetNext(pos);ar m_sGroupName;ar m_sComment;/other listar nCount;CObject*pInfo;whi
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- MFC 编程 案例 chapter013
限制150内