关于CArchive类的问题

Leon828190 2004-05-09 10:22:07
请教CArchive类的基本用法
谢谢!
...全文
330 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
Leon828190 2004-05-10
  • 打赏
  • 举报
回复
好人啊!
狂放之歌 2004-05-10
  • 打赏
  • 举报
回复
mark...:)
菜牛 2004-05-10
  • 打赏
  • 举报
回复
以上摘自MSDN,自己可写不出来。
菜牛 2004-05-10
  • 打赏
  • 举报
回复
通过存档存储及加载 CObject 需要额外注意。在某些情况下,应调用对象的 Serialize 函数,其中,CArchive 对象是 Serialize 调用的参数,与使用 CArchive 的“<<”或“>>”运算符不同。要牢记的重要事实是:CArchive 的“>>”运算符基于由存档先前写到文件的 CRuntimeClass 信息构造内存中的 CObject。

因此,是使用 CArchive 的“<<”和“>>”运算符还是调用 Serialize,取决于是否需要加载存档基于先前存储的 CRuntimeClass 信息动态地重新构造对象。在下列情况下使用 Serialize 函数:

反序列化对象时,预先知道对象的确切的类。
反序列化对象时,已为其分配了内存。
警告 如果使用 Serialize 函数加载对象,也必须使用 Serialize 函数存储对象。不要使用 CArchive 的“<<”运算符先存储,然后使用 Serialize 函数进行加载;或使用 Serialize 函数存储,然后使用 CArchive 的“>>”运算符进行加载。
以下示例阐释了这些情况:

class CMyObject : public CObject
{
// ...Member functions
public:
CMyObject() { }
virtual void Serialize( CArchive& ar ) { }

// Implementation
protected:
DECLARE_SERIAL( CMyObject )
};


class COtherObject : public CObject
{
// ...Member functions
public:
COtherObject() { }
virtual void Serialize( CArchive& ar ) { }

// Implementation
protected:
DECLARE_SERIAL( COtherObject )
};


class CCompoundObject : public CObject
{
// ...Member functions
public:
CCompoundObject();
virtual void Serialize( CArchive& ar );

// Implementation
protected:
CMyObject m_myob; // Embedded object
COtherObject* m_pOther; // Object allocated in constructor
CObject* m_pObDyn; // Dynamically allocated object
//..Other member data and implementation

DECLARE_SERIAL( CCompoundObject )
};

IMPLEMENT_SERIAL(CMyObject,CObject,1)
IMPLEMENT_SERIAL(COtherObject,CObject,1)
IMPLEMENT_SERIAL(CCompoundObject,CObject,1)


CCompoundObject::CCompoundObject()
{
m_pOther = new COtherObject; // Exact type known and object already
//allocated.
m_pObDyn = NULL; // Will be allocated in another member function
// if needed, could be a derived class object.
}

void CCompoundObject::Serialize( CArchive& ar )
{
CObject::Serialize( ar ); // Always call base class Serialize.
m_myob.Serialize( ar ); // Call Serialize on embedded member.
m_pOther->Serialize( ar ); // Call Serialize on objects of known exact type.

// Serialize dynamic members and other raw data
if ( ar.IsStoring() )
{
ar << m_pObDyn;
// Store other members
}
else
{
ar >> m_pObDyn; // Polymorphic reconstruction of persistent
// object
//load other members
}
}
总之,如果可序列化的类将嵌入的 CObject 定义为成员,则不应使用该对象的 CArchive 的“<<”和“>>”运算符,而应调用 Serialize 函数。同时,如果可序列化的类将指向 CObject(或从 CObject 派生的对象)的指针定义为成员,但在自己的构造函数中将其构造为其他对象,则也应调用 Serialize。

菜牛 2004-05-10
  • 打赏
  • 举报
回复
CArchive 提供“<<”和“>>”运算符,用于向文件中写入简单的数据类型和 CObjects 以及从文件中读取它们。

通过存档将对象存储在文件中

以下示例显示了如何通过存档将对象存储在文件中:
CArchive ar(&theFile, CArchive::store);
WORD wEmployeeID;
...
ar << wEmployeeID;
从先前存储在文件中的值加载对象

以下示例显示了如何从先前存储在文件中的值加载对象:
CArchive ar(&theFile, CArchive::load);
WORD wEmployeeID;
...
ar >> wEmployeeID;
通常,通过 CObject 派生类的 Serialize 函数中的存档将数据存储到文件中或从文件中加载数据,必须已用 DECLARE_SERIALIZE 宏来声明这些函数。将 CArchive 对象的引用传递到 Serialize 函数。调用 CArchive 对象的 IsLoading 函数以确定是否已调用 Serialize 函数来从文件中加载数据或将数据存储到文件中。

可序列化的 CObject 派生类的 Serialize 函数通常具有以下形式:

void CPerson::Serialize(CArchive& ar)
{
CObject::Serialize(ar);
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
上面的代码模板与 AppWizard 为该文档(从 CDocument 派生的类)的 Serialize 函数所创建的代码模板完全相同。由于存储代码和加载代码总是并行,该代码模板有助于写的代码更容易复查,如下例中所示:

void CPerson:Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
ar << m_strName;
ar << m_wAge;
}
else
{
ar >> m_strName;
ar >> m_wAge;
}
}
库将 CArchive 的“<<”和“>>”运算符定义为第一操作数,将下列数据类型和类类型定义为第二操作数:

CObject* SIZE 和 CSize float
WORD CString POINT 和 CPoint
DWORD BYTE RECT 和 CRect
double LONG CTime 和 CTimeSpan
int COleCurrency COleVariant
COleDateTime COleDateTimeSpan

注意 通过存档存储及加载 CObjects 需要额外注意。有关更多信息,请参见通过存档存储和加载 CObjects。
CArchive 的“<<”和“>>”运算符总是返回 CArchive 对象的引用,该引用为第一操作数。这使您可以链接运算符,如下所示:

BYTE bSomeByte;
WORD wSomeWord;
DWORD wSomeDoubleWord;
...
ar << bSomeByte << wSomeWord << wSomeDoubleWord;
菜牛 2004-05-10
  • 打赏
  • 举报
回复
什么是 CArchive 对象

CArchive 对象提供了一个类型安全缓冲机制,用于将可序列化对象写入 CFile 对象或从中读取可序列化对象。通常,CFile 对象表示磁盘文件;但是,它也可以是表示“剪贴板”的内存文件(CSharedFile 对象)。

给定的 CArchive 对象要么存储数据(即写入数据或将数据序列化),要么加载数据(即读取数据或将数据反序列化),但决不能同时进行。CArchive 对象的寿命只限于将对象写入文件或从文件读取对象的一次传递。因此,需要两个连续创建的 CArchive 对象将数据序列化到文件,然后从文件反序列化数据。

当存档将对象存储到文件时,存档将 CRuntimeClass 名称附加到这些对象。然后,当另一个存档将对象从文件加载到内存时,将基于这些对象的 CRuntimeClass 动态地重新构造 CObject 派生的对象。通过存储存档将给定对象写入文件时,该对象可能被引用多次。然而,加载存档将仅对该对象重新构造一次。有关存档如何将 CRuntimeClass 信息附加到对象以及重新构造对象(考虑可能的多次引用)的详细信息,请参见技术说明 2。

将数据序列化到存档时,存档积累数据,直到其缓冲区被填满为止。然后,存档将其缓冲区写入 CArchive 对象指向的 CFile 对象。同样,当您从存档中读取数据时,存档会将数据从文件读取到它的缓冲区,然后从缓冲区读取到反序列化的对象。这种缓冲减少了物理读取硬盘的次数,从而提高了应用程序的性能。


创建 CArchive 对象有两种方法:

通过框架隐式创建 CArchive 对象
显式创建 CArchive 对象
通过框架隐式创建 CArchive 对象
最普通且最容易的方法是使框架代表“文件”菜单上的“保存”、“另存为”和“打开”命令为文档创建 CArchive 对象。

以下是应用程序的用户从“文件”菜单上发出“另存为”命令时,框架所执行的操作:

显示“另存为”对话框并从用户获取文件名。
打开用户命名的文件作为 CFile 对象。
创建指向该 CFile 对象的 CArchive 对象。在创建 CArchive 对象时,框架将模式设置为“存储”(即写入或序列化),而不是“加载”(即读取或反序列化)。
调用在 CDocument 派生类中定义的 Serialize 函数,将 CArchive 对象的引用传递给该函数。
然后,文档的 Serialize 函数将数据写入 CArchive 对象(刚作了解释)。从 Serialize 函数返回时,框架先销毁 CArchive 对象,再销毁 CFile 对象。

因此,如果让框架为文档创建 CArchive 对象,您所要做的一切是实现写入存档和从存档中读取的文档的 Serialize 函数。您还必须为文档的 Serialize 函数直接或间接依次序列化的任何 CObject 派生对象实现 Serialize。

显式创建 CArchive 对象
除了通过框架将文档序列化之外,在其他场合也可能需要 CArchive 对象。例如,可能要序列化到达或来自剪贴板的数据,由 CSharedFile 对象表示。或者,可能要使用用户界面来保存与框架提供的文件不同的文件。在这种情况下,可以显式创建 CArchive 对象。使用下列过程,用与框架采用的相同方式来执行此操作。

显式创建 CArchive 对象

构造 CFile 对象或从 CFile 导出的对象。
按照下面示例所示,将 CFile 对象传递到 CArchive 的构造函数:
CFile theFile;
theFile.Open(..., CFile::modeWrite);
CArchive archive(&theFile, CArchive::store);
CArchive 构造函数的第二个参数是指定存档将用于向文件中存储数据还是用于从文件中加载数据的枚举值。对象的 Serialize 函数通过调用存档对象的 IsStoring 函数来检查该状态。

当完成向 CArchive 对象存储数据或从该对象中加载数据时,关闭该对象。虽然 CArchive 对象(和 CFile 对象)会自动关闭存档(和文件),好的做法是显式执行,因为这使从错误恢复更为容易。有关错误处理的更多信息,请参见异常:捕捉和删除异常一文。

关闭 CArchive 对象

以下示例阐释了如何关闭 CArchive 对象:
archive.Close();
theFile.Close();



16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧