42
第 9 第 MFC 第第第第第第第 9.1 CFile 第 9.2 CArchive 第 9.3 第第第第第第 9.4 第 DECALRE_SERIAL 第 IMPLEMENT_SERIAL 9.5 MFC 第第第第第第第第第第第

第 9 章 MFC 的文件处理机制

  • Upload
    ena

  • View
    149

  • Download
    5

Embed Size (px)

DESCRIPTION

第 9 章 MFC 的文件处理机制. 9.1 CFile 类 9.2 CArchive 类 9.3 对象的序列化 9.4 宏 DECALRE_SERIAL 和 IMPLEMENT_SERIAL 9.5 MFC 文件命令的默认处理流程. FILE structure. Stores information about current state of stream; used in all stream I/O operations. MFC 的文件处理机制主要有两种: 通过 CFile 类实现文件的读写; - PowerPoint PPT Presentation

Citation preview

第 9 章 MFC 的文件处理机制

9.1 CFile 类9.2 CArchive 类9.3 对象的序列化9.4 宏 DECALRE_SERIAL 和

IMPLEMENT_SERIAL

9.5 MFC 文件命令的默认处理流程

MFC 的文件处理机制主要有两种:1) 通过 CFile 类实现文件的读写;2) 通过对象的序列化 (Serialization) 实现数据

的存储和读写

FILE structureStores information about current state of stream; used in all stream I/O operations

序列化的基本思想:一个类应该能够对自己的成员变量的数据进行读写操作,对象可以通过读操作而重新创建。由于 CObject 类提供了保存和加载对象状态的基本功能,所以一般类的对象都具备将状态值写入磁盘或从磁盘中读出的方法,这种对象的保存和恢复的过程称为序列化。

内存 磁盘

对象成员(派生自CObject )

文件内存地址

9.1 CFile 类CFile 类中包含了大量的文件操作函数,1) 用户可以使用 CFile 类实现文件的 read 、 write 、append 、 delete 等操作。2) 相对于其他的文件操作方式, CFile 更显得直接和自由。3) 与 C/C++ 中的文件操作方式接近

1. CFile 类常用的成员函数 ( 表 9-1)

2. 文件的创建和打开

创建 CFile 类的对象,并使其与磁盘文件之间建立关系。CFile 的构造函数:CFile::CFile()

CFile::CFile(int hFile);

CFile::CFile(LPCTSTR lpszFileName, UINT nOpenFlags );

文件名 ( 字符串常量 ) 文件打开模式

9.1 CFile 类

9.1 CFile 类

打开方式 说明CFile::modeCreate 如果文件已经存在,则长度置 0

CFile::modeNoTruncate与 modeCreate组合使用,如果文件已存在,则其长度不为 0

CFile::modeRead 只读方式打开CFile::modeReadWrite 读写方式CFile::modeWrite 只写方式CFile::ShareExclusive 独占方式打开

表 9-2 几种常用的文件创建及打开方式

例 9-1

长度=0

长度!=0

9.1 CFile 类3. 文件的读写读写位置的定位:LONG CFile::Seek(LONG lOff, UINT nFrom);

偏移字节数 偏移起点位置

nFrom的取值 说明CFile::begin 文件首CFile::current 当前位置CFile::end 文件尾

表 9-3 nFrom 的取值

void CFile::SeekToBegin()

void CFile::SeekToEnd()

9.1 CFile 类文件的写操作void CFile::Write(const void * lpBuf, UINT nCount);

待写数据的缓冲区 待写数据的字节数

例 9-2

9.1 CFile 类

文件的读操作UINT CFile::Read(void * lpBuf, UINT nCount);

读缓冲区指针 读取的字节数

例 9-3

9.1 CFile 类4. CFile 的派生类 CMemFile

将一块内存区域当作文件来实现读写操作,便于在程序的独立模块之间交换数据。

9.1 CFile 类5. CFileFind 类——查找文件

例 9-7

9.1 CFile 类文件属性的访问

9.2 CArchive 类

为什么引入 CArchive 类?-为了在磁盘文件中保存应用程序类对象,并通过读取在内存中复原它们。如何实现类对象的存储和读写?- 类的序列化( Serialization )机制,自动化的存储机制,保存对象,动态恢复对象。- 形如: ar << a << b << … << z; ar >> a >> b >> …

>> z;

为什么不使用 CFile 类来实现?- 类的成员比较复杂(访问属性,继承,嵌套其他的类对象),因此存储也变得复杂。- 复原这些对象 ( 动态地创建对象 ) 也需要一些机制来实现。

FileApp Write

Read

9.2 CArchive 类

9.2 CArchive 类1. 运算符重载

为了便于文件的读写操作, CArhive 重载了两个运算符,对基本数据类型和 CObject 的派生类读写予以支持:

插入符 <<

提取符 >>

2. 与 CFile 的关系包装了CFile

9.2 CArchive 类

BOOL CArchive::IsLoading()

- 当 CArchive 类处于读状态时,返回 TRUE

BOOL CArchive::IsStoring()

- 当 CArchive 类处于写状态时,返回 TRUE

CFile 操作完毕,不要忘记调用 CFile::Close()

同理, CArchive 操作完毕,也要调用 CArchive::Close()

9.2 CArchive 类

例 9-4

9.3 对象的序列化

序列化 (Serialization) :是 OOP 中 Object 数据的存储和恢复的一种文件读写机制。

对象→字节流,打包字节流→对象,解包对象的这种存储技术称为序列化。

1. 序列化的基本概念

写入时,依据嵌套关系依次调用自己的“保存”成员函数,完成数据的写入操作。读取时,根据嵌套关系实现自身数据的读取操作。

数 据 的 打包过程

数 据 的 解包过程

9.3 对象的序列化

2. MFC 的 Serialize 函数virtual void CObject::Serialzie(CArchive& ar);

在标准的 MFC 应用程序的读写过程中,程序首先调用文档类的序列化函数 Serialize() 。

9.3 对象的序列化

9.3 对象的序列化

3. MFC 应用程序的序列化过程

视图类中定义的菜单命令响应函数

9.3 对象的序列化4. 序列化的顺序

1)对于嵌套对象,必须由外到内调用各个对象的序列化函数;2)写入顺序与读取顺序必须相同。

例 9-5

响应文件菜单的打开与保存命令

本例中的 CLetter不能解决动态对象的

序列化问题。

9.3 对象的序列化5. Serialize 函数的局限性

1)只能顺序读写文件,不能随机操作文件;2)只能一次性读写文件的所有部分,不能部分读取文件

的内容;3)只能操作二进制文件,不能处理文本文件;4)不能操作数据库文件;5)不能共享式操作文件。

9.4 宏 DECLARE_SERIAL 与 IMPLEMENT_SERIAL

序 列 化 的 机 制 , 要 求 可 以 动 态 地 创 建 对 象 , 而 派 生 自CObject 类的子类不具备动态创建能力,因此需要为其增加动态创建能力。另外,重载 >> 运算符,用于读取对象创建信息。

为此, MFC 采用一对宏:DECLARE_SERIAL & IMPLEMENT_SERIAL

DECLARE_SERIAL( class_name )

RemarksDECLARE_SERIAL generates the C++ header code necessary for a

CObject-derived class that can be serialized.

If DECLARE_SERIAL is included in the class declaration, then

IMPLEMENT_SERIAL must be included in the class

implementation.

The DECLARE_SERIAL macro includes all the functionality of

DECLARE_DYNAMIC and DECLARE_DYNCREATE.

9.4 宏 DECLARE_SERIAL 与 IMPLEMENT_SERIAL

DECLARE_SERIAL( class_name )

#define DECLARE_SERIAL(class_name) \

DECLARE_DYNCREATE(class_name) \

friend CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb);

9.4 宏 DECLARE_SERIAL 与 IMPLEMENT_SERIAL

IMPLEMENT_SERIAL( class_name, base_class_name, wSchema )RemarksGenerates the C++ code necessary for a dynamic CObject-derived class with run-time access to the class name and position within the hierarchy.

#define IMPLEMENT_SERIAL(class_name, base_class_name, wSchema) \

CObject* PASCAL class_name::CreateObject() { return new class_name; }

IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema,

class_name::CreateObject) \

CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb){

pOb = (class_name*)ar.ReadObject(RUNTIME_CLASS(class_name));return ar;

}

9.4 宏 DECLARE_SERIAL 与 IMPLEMENT_SERIAL

CArchive::ReadObject  Reads object data from the archive and constructs an object of the appropriate type.

9.4 宏 DECLARE_SERIAL 与 IMPLEMENT_SERIAL

CONCLUSION :

1) 从 CObject 派生,以便重载 Serialize()

• 在 .h 文件中使用 DECLARE_SERIAL ,在 .cpp 中使用IMPLEMENT_SERIAL

• 必须定义一个无参的构造函数,满足对象动态创建的需要1) 因为序列化与 Document 类紧密相关,且从其 Serialize() 开

始,故程序中的数据应作为 Document 类的成员。

9.4 宏 DECLARE_SERIAL 与 IMPLEMENT_SERIAL

9.4 宏 DECLARE_SERIAL 与 IMPLEMENT_SERIAL

例 9-6

例 9-6a

文件

9.5 MFC 文件命令的默认处理流程

菜单命令 File->Open

OnOpenDocument(…)

GetFile(…)构造 CArchive 对象

DeleteContents(…)

Serialize(…)

SetModifiedFlag(FALSE)

1. 文件打开

菜单命令 File->New

OnNewDocument(…)

DeleteContents(…)

SetModifiedFlag(FALSE)

文档对象

9.5 MFC 文件命令的默认处理流程1. 文件打开

菜单命令 File->Save As

OnSaveDocument(…)

GetFile(…)构造 CArchive 对象

DeleteContents(…)

Serialize(…)

SetModifiedFlag(FALSE)

9.5 MFC 文件命令的默认处理流程2. 保存文件

菜单命令 File->Save

文件保存完成

9.5 MFC 文件命令的默认处理流程可以重载 CDocument 类的 OnOpenDocument 和

OnSaveDocument 成员函数,从中获取文件名。如

详见例 fileDemo