65.9K
CodeProject 正在变化。 阅读更多。
Home

序列化入门 - 第 1 部分

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.64/5 (40投票s)

2002年2月18日

CPOL

2分钟阅读

viewsIcon

387341

本教程描述了如何轻松地序列化一个简单的对象。

本文是关于序列化的 3 部分教程的第一部分。

  • 第 1 部分介绍了序列化的基础知识。
  • 第 2 部分 解释了如何优雅地处理读取无效的数据存储以及支持版本控制。
  • 第 3 部分 描述了如何序列化复杂对象。

序列化是将对象写入或从持久性存储介质(例如磁盘文件)读取的过程。 序列化一个对象需要 3 个要素

  • 一个代表数据文件的 CFile 对象
  • 一个提供序列化上下文的 CArchive 对象
  • 被序列化的对象

Serialization data flow

第 1 步 - 打开数据文件

要将对象序列化到文件 "foo.dat",请使用适当的访问模式打开文件。 在本例中,该文件以独占读/写访问模式打开。

  // Open file "foo.dat"
  CFile* pFile = new CFile();
  ASSERT (pFile != NULL);
  if (!pFile->Open ("foo.dat", CFile::modeReadWrite | CFile::shareExclusive)) {
      // Handle error
      return;
  }

第 2 步 - 连接归档文件

接下来,将一个 CArchive 对象连接到该文件。 归档文件提供了一种有效的通道,用于持久性存储。 您可以将数据序列化到归档文件和从归档文件中序列化数据,而不是直接读写文件。 归档文件需要知道您是使用它来读取还是写入数据。 在本例中,我们假设要写入数据。

  // Create archive ...
  bool bReading = false;  // ... for writing
  CArchive* pArchive = NULL;
  try
  {
    pFile->SeekToBegin();
    UINT uMode = (bReading ? CArchive::load : CArchive::store);
    pArchive = new CArchive (pFile, uMode);
    ASSERT (pArchive != NULL);
  }
  catch (CException* pException)
  {
    // Handle error
    return;
  }

第 3 步 - 序列化对象

最后,我们通过调用对象的 serialize() 方法来序列化对象。 serialize() 只是我们自己创建的一个方法。 它与 MFC 的 CObject::Serialize() 无关。 此外,您不必从 CObject 派生对象。 我们的 serialize() 方法接受一个指向 CArchive 的指针并返回一个整数状态。

  int CFoo::serialize
    (CArchive* pArchive)
  {
    int nStatus = SUCCESS;

    // Serialize the object ...
    ...
    
    return (nStatus);
  }

稍后我们将开始实际的序列化过程。 与此同时,让我们认识到几个重要的点

  • 使用相同的方法 CFoo::serialize() 来从/向持久性存储读取/写入对象。
  • CFoo::serialize() 不知道任何关于正在访问的数据文件的信息。

假设 CFoo 代表一个员工记录,其中包含几个数据成员。

  class CFoo
  {
    // Construction/destruction
    public:
      CFoo::CFoo();
      virtual CFoo::~CFoo();

    // Methods
    public:
      int serialize (CArchive* pArchive);

    // Data members
    public:
      CString  m_strName;  // employee name
      int      m_nId;      // employee id
  };

我们使用 CArchive 的流运算符 <<>> 来从/向归档文件读取/写入数据成员。 CArchive 知道如何序列化简单的数据类型,如 intfloatDWORD 和对象(如 CString)。 归档文件也知道它处于读取还是写入模式。 您可以通过调用 CArchive::IsStoring() 来查询其模式。 然后,CFoo 的序列化方法可以写成

  int CFoo::serialize
    (CArchive* pArchive)
  {
    int nStatus = SUCCESS;

    // Serialize the object ...
    ASSERT (pArchive != NULL);
    try
    {
      if (pArchive->IsStoring()) {
         // Write employee name and id
         (*pArchive) << m_strName;
         (*pArchive) << m_nId;
      }
      else {
         // Read employee name and id
         (*pArchive) >> m_strName;
         (*pArchive) >> m_nId;
      }
    }
    catch (CException* pException)
    {
      nStatus = ERROR;
    }
    return (nStatus);
  }

第 4 步 - 清理

完成序列化后,您应该通过关闭归档文件和数据文件来清理。

  pArchive->Close();
  delete pArchive;
  pFile->Close();
  delete pFile();

结论

好了,这就是它 - 序列化(非常小)的概要。 在 第 2 部分 中,我们将了解如何优雅地处理读取无效数据存储以及支持对象的不同版本。 在 第 3 部分 中,我们将了解如何序列化复杂对象。

© . All rights reserved.