程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 新手指南-序列化篇之二

新手指南-序列化篇之二

編輯:關於C語言

在第一部分,我們學到了如何通過CArchive類的serialize()函數來序列化一個簡單對象。象下面的程序這樣:

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_ALL (pException)

    {

      nStatus = ERROR;

    }

    END_CATCH_ALL

 

    return (nStatus);

  }

這段代碼有一個問題,如果我們錯誤的從數據文件中去讀取並不存在的信息會怎麼樣?如果數據文件中在CString之後不是一個整數,那麼serialize()函數將返回ERROR。這也不錯,但是如果我們可以給錯誤定位,並返回一個更加詳細的錯誤信息,比如INVALID_DATAFILE,那就更好了。我們可以通過對象簽名來確認我們是在讀取一個有效的數據文件。

對象簽名

對象簽名就是用一個字符串來識別一個對象。我們修改Cfoo類的定義來增加一個簽名:

class CFoo

  {

    ...

 

    // Methods

    public:

      ...

      CString getSignature();

 

    // Data members

      ...

    protected:

      static const CString  Signature;  // object signature

  };

簽名在Foo.cpp中申明:

// Static constants

  const CString CFoo::Signature = "FooObject";

下一步,我們修改serialize()函數,在序列化對象的數據成員前先序列化這個簽名。如果遇到無效的簽名,或者簽名丟失,那麼可以認為我們在試圖讀取一個並不包含有Cfoo對象的數據存儲。以下是讀取有簽名的對象的流程:

 


以下是流程實現代碼:

int CFoo::serialize

    (CArchive* pArchive)

  {

    int nStatus = SUCCESS;

    bool bSignatureRead = false;

 

    // Serialize the object ...

    ASSERT (pArchive != NULL);

    TRY

    {

      if (pArchive->IsStoring()) {

         // Write signature

         (*pArchive) << getSignature();

 

         // Write employee name and id

         (*pArchive) << m_strName;

         (*pArchive) << m_nId;

      }

      else {

         // Read signature - complain if invalid

         CString strSignature;

         (*pArchive) >> strSignature;

         bSignatureRead = true;

         if (strSignature.Compare (getSignature()) != 0) {

            return (INVALID_DATAFILE);

         }

 

         // Read employee name and id

         (*pArchive) >> m_strName;

         (*pArchive) >> m_nId;

      }

    }

    CATCH_ALL (pException)

    {

      nStatus = bSignatureRead ? ERROR : INVALID_DATAFILE;

    }

    END_CATCH_ALL

 

    return (nStatus);

  }

你必須確保你所有的對象都有唯一的簽名。具體的簽名內容並不重要。如果你正在開發一批產品,那麼在公司范圍內增加一個對象簽名注冊步驟是非常有幫助的。另一方面,開發者將不會給不同的對象使用相同的簽名。如果你想讓你的數據文件更難以被反解,那麼你應該使用一個與對象名稱沒有明顯任何關系的簽名。

版本

如果你在產品的生命周期內進行升級,那麼你也許要通過增加或者刪除數據成員來修改Cfoo類結構。如果你只是為Cfoo發布新的版本,並且試圖從數據存儲中讀取舊版本的對象,那麼將會失敗。這明顯是不可以接受的。Cfoo的任何版本都應該可以讓一個更舊版本恢復。

換句話說,Cfoo的序列化方法應該是向前兼容的。這個問題通過給對象增加版本是很容易完成的。與給對象增加簽名相同,我們增加一個整數常量來指定這個對象的版本號。

class CFoo

  {

    ...

 

    // Methods

    public:

      ...

      CString getSignature();

      int     getVersion();

 

    // Data members

      ...

    protected:

      static const CString  Signature;  // object signature

      static const int      Version;    // object version

  };

對象的版本號在Foo.cpp中申明

  // Static constants

  const CString CFoo::Signature = "FooObject";

  const int     CFoo::Version = 1;

下一步,我們修改serialize()函數,在序列化簽名之後,序列化對象的數據成員之前序列化版本。如果遇到更新的版本,我們試圖讀取一個對象不支持的版本,那麼,在下面的例子中,我們就返回一個狀態標志UNSUPPORTED_VERSION。

int CFoo::serialize

    (CArchive* pArchive)

  {

    int nStatus = SUCCESS;

    bool bSignatureRead = false;

    bool bVersionRead = false;

 

    // Serialize the object ...

    ASSERT (pArchive != NULL);

    TRY

    {

      if (pArchive->IsStoring()) {

         // Write signature and version

         (*pArchive) << getSignature();

         (*pArchive) << getVersion();

 

         // Write employee name and id

         (*pArchive) << m_strName;

         (*pArchive) << m_nId;

      }

<

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved