TN002: Persistent Object Data Format(永久物件的資料格式) (轉)
TN002: Persistent Data Format(永久的資料格式):namespace prefix = o ns = "urn:schemas--com::office" />
摘要:
這是篇筆記主要描述支援永久物件的MFC和當物件資料儲存成時的格式。
1、 MFC利用緊湊的二進位制格式對資料進行儲存,每個物件在檔案中只存在一個實體。物件自已的Serialize()才是提供真正的儲存。
2、 Carchive::WriteObject透過寫入資料頭來重建物件。資料頭包括物件型別和物件狀態兩個部分。此函式同樣也負責寫入一識別符號,以此來保持一個物件只有一份複製。
3、 讀取和寫入物件需要依依靠幾個預定義的常量,如下表:
Tag(識別符號)
Description(描述)
wNullTag
用於一個指向NULL的物件.
wNewClassTag
指出其後面是一個新的物件
wOldClassTag
指出將要讀取的是一個已讀取過的物件
wClassTag
類指示符
wBigObjectTag
0x8000000 指示一個大類標記
nMaxMapCount
0x3FFFFFFE 表示最大的mapCount值
4、 當儲存物件時Carchive維持了一個把要儲存的物件對映到一個32位識別符號PID的CmapPtrToPtr物件(m_pStoreMap)。PID的值是從1始的,PID只在它的作用域範圍內有效。
5、 儲存物件所用到的函式及相關程式碼:
void CArchive::WriteObject(const CObject* pOb)
{
// 物件可以為 NULL
D nObIndex;
// 初始化m_pStoreMap
MapObject(NULL);
if (pOb == NULL)
{
// 儲存NULL指標標誌
*this << wNullTag;
}
else if ((nObIndex = (DWORD)(*m_pStoreMap)[(void*)pOb]) != 0)
// assumes initialized to 0 map
{
//儲存已儲存過物件的INDEX
if (nObIndex < wBigObjectTag)
*this << (WORD)nObIndex;
else
{
*this << wBigObjectTag;
*this << nObIndex;
}
}
else
{
// 寫入示儲存過的物件
CRuntimeClass* pClassRef = pOb->GetRuntimeClass();
WriteClass(pClassRef);
// enter in stored object table, checking for overflow
CheckCount();
(*m_pStoreMap)[(void*)pOb] = (void*)m_nMapCount++;
// 使物件自身進行系列化
((CObject*)pOb)->Serialize(*this);
}
}
void CArchive::WriteClass(const CRuntimeClass* pClassRef)
{
// 確認pStoreMap已被初始化
MapObject(NULL);//在這裡實際沒有做什麼事情
// 寫入物件的ID和指示符並把指示符放在高位.
// new object follows
//假定map以初始化為0
DWORD nClassIndex;
if ((nClassIndex = (DWORD)(*m_pStoreMap)[(void*)pClassRef]) != 0)
{
// previously seen class, write out the index tagged by high bit
if (nClassIndex < wBigObjectTag)
*this << (WORD)(wClassTag | nClassIndex);
else
{
*this << wBigObjectTag;
*this << (dwBigClassTag | nClassIndex);
}
}
else
{
// 儲存新物件
*this << wNewClassTag;
//儲存RUNTIME_CLASS物件所需的資訊(如:物件名字)
pClassRef->Store(*this);
// 儲存新物件的引用(參考)到MAP中
CheckCount();
(*m_pStoreMap)[(void*)pClassRef] = (void*)m_nMapCount++;
}
}
6、 當ReadObject從檔案中讀取物件時透過判斷PID是否大於當前陣列的上限,如果大於則是一個新的物件。
7、 實現多版本化所要做的幾點和MFC內部實現的部份程式碼。
l 在IMPLEMENT_SERIAL中要使nSchema為VERSIONABLE_SCHEMA與當前版本號進行或運算所得的值。
l 在Serialize中透過GetObjectSchema來獲版本號,並進行相應處理。
具體程式碼如下:
#define VERSIONABLE_SCHEMA (0x80000000)
IMPLEMENT_SERIAL(CMyObject, CObject, VERSIONABLE_SCHEMA|1)
void CMyObject::Serialize(CArchive& ar)
{
if (ar.IsLoading())
{
int nVersion = ar.GetObjectSchema();
switch(nVersion)
{
case 0:
// read in previous version of
// this object
break;
case 1:
// read in current version of
// this object
break;
default:
// report unknown version of
// this object
break;
}
}
else
{
// Normal storing code goes here
}
}
8、 在一些情況下需要直接Serialize,這樣帶來了一些好處但也帶來的不好的地方。主要有四個方面:
l 可以使檔案體更小,而且可以支援更多的檔案格式。
l ReadObject和WriteObject以及一些與它們有關的東西不會連線到你的程式中去,除非你要支援更多通用物件的存檔方案。
l 反系列化時需要自行處理更多的事情。
l 不能呼叫CArchive::GetObjectSchema或者要使CArchive::GetObjectSchema返回-1來表示未知版本。
由於直接呼叫Serialize會造成有時在子物件中要儲存父文件物件的指標,這需要兩步來實現:1、在子物件中必需顯式地儲存一個指向父文件的back pointer;2、在back pointer存檔之前,透過呼叫CArchive::MapObject把Cdocument對映一個PID。
注:具體內部流程參考《深入淺出MFC》PART4—P60
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-993350/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- C++永久物件儲存 (Persistent Object Storage for C++) (轉)C++物件Object
- 我理解的Persistent Object Identity in HibernateObjectIDE
- oracle data Format Models---二(轉)OracleORM
- 把JSON資料格式轉換為Python的類物件JSONPython物件
- 【轉】Python格式化字串str.format()Python字串ORM
- JAVA字串格式化-String.format()的使用 (轉載)Java字串格式化ORM
- (轉)修改oracle預設日期格式 nls_date_formatOracleORM
- 使用.format格式化json格式的入參ORMJSON
- EJB設計模式之Data Transfer Object (轉)設計模式Object
- [PY3]——內建資料結構(4)——字串格式化(format)資料結構字串格式化ORM
- C#中string.format格式轉化總結C#ORM
- OAF export data from VO in xlsx formatExportORM
- Hive資料格式轉換Hive
- MXNet的資料格式轉化為tensorflow訓練用的資料格式
- ASP.NET設定資料格式與String.Format使用總結ASP.NETORM
- OBJECT_ID和DATA_OBJECT_IDObject
- oracle 引數LOG_ARCHIVE_FORMAT 的格式OracleHiveORM
- clang-format的程式碼格式化ORM
- object_id 與data_object_id 的區別Object
- object_id與data_object_id的關係Object
- 醫學影象資料格式和格式轉換
- 用兩種方法把JSON資料格式轉換為Python的類物件JSONPython物件
- Clang-format格式標準化ORM
- 善用 Format 來格式化字串ORM字串
- Redis 資料結構與物件編碼 (Object Encoding)Redis資料結構物件ObjectEncoding
- layui tree資料格式轉換UI
- XML資料島(XML Data Island) (轉)XML
- Truncate and data_object_idObject
- Object物件的屬性Object物件
- Differences between DATA_OBJECT_ID and OBJECT_IDObject
- object_id 及 data_object_id (oracle)ObjectOracle
- OBJECT_ID、DATA_OBJECT_ID與truncate的本質Object
- data型別的Url格式:把小資料直接嵌入到Url中型別
- JSONObject應用Json字串和Object物件之間的轉換,Map封裝資料思路JSONObject字串物件封裝
- js字串string轉object物件 - 方法篇JS字串Object物件
- js 物件轉為js陣列 && Object方法JS物件陣列Object
- Object Pascal:從物件指標談起 (轉)Object物件指標
- Oracle資料庫資料物件分析(轉)Oracle資料庫物件