MFC/VC++ 怎样将C++对象存储到数据库并读取出来

来源:互联网 发布:淘宝网店开店费用 编辑:程序博客网 时间:2024/05/17 06:19

http://www.vckbase.com/index.php/wv/1190.html

http://blog.csdn.net/wirror800/article/details/4003995

4 使用C++将对象进行序列化的几种方法

使用C++进行对象序列化的方法可以有以下三种:基于Boost库的方法;基于.Net Framework的方法;以及基于MFC的方法。本章将就三种方法的实现机制、实现步骤,以及注意事项进行说明。

由于我们的开发环境在Windows下,部署环境在Unix下,因此我们的开发需要使用两个平台都可以兼容的技术。经过验证,基于.Net和基于MFC的方法仅适用于Windows的环境,而Boost库在Windows和Unix下都有相应的版本,因此在项目中应优先考虑使用Boost库进行对象的序列化。尽管如此,本文中仍然列出使用.Net和MFC进行序列化的方法,以供参考。三种方法相应的代码实现的例子将附在文章之后。

MFC中的序列化:

实现步骤

实现序列化的的类需要满足一系列条件:

1. 该类需要从CObject类派生(可以是间接派生);

2. 在类中中进行DECLARE_SERIAL宏定义;

3. 类存在有缺省的构造函数;

4. 类中实现了Serialize(CArchive&)函数,并且在其中调用基类的序列化函数;

5. 使用IMPLEMENT_SERIAL宏指明类名及版本号。

满足了这些条件之后,就可以进行序列化与反序列化了。

序列化时,首先,实例化一个CArchive类的对象,将其与输出文件相关联;其次,利用CArchive类的<<运算符重载将需要序列化的对象保存在文件中。

反序列化时,将CArchive类的对象与保存对象的文件相关联;然后新建一个需要反序列化的对象,利用CArchive类的>>运算符重载将文件里的内容恢复到需要反序列化的对象中。

 注意事项

使用这种方法需要注意的是:

l  需要包含afx.h头文件;

l  它不支持string类型的序列化,但是支持CString类型的序列化;

l  需要将项目属性中的MFC属性配置为“在共享DLL中使用MFC”或“在静态库中使用MFC”,否则编译时会报错。


举例:

一、新建一个继承于 CObject 的子类 CLine;

头文件:Line.h

01.classCLine :public CObject
02.{
03.private:
04.LOGPEN m_logPen;//画笔
05.COLORREFm_crBackColor;
06.CArray<CPoint, CPoint &> m_PointArray;//标记类对应框
07. 
08.public:
09.intGetSize();
10.CPoint GetPoint(intpos);
11.voidDrawLine(CDC *pDC,CPoint pt1,CPoint pt2,CRect rc);
12.voidDrawBackGround(CDC *pDC,CRect rect);
13.voidDrawPoint(CDC *pDC, CRect rect);
14.voidSetWidth(intiWidth);
15.COLORREFGetColor();
16.voidSetColor(COLORREFcolor);
17. 
18.COLORREFGetBkColor();
19.voidSetBkColor(COLORREFcolor);
20. 
21.voidAddPoint(CPoint point);
22.voidClear();
23.CLine();
24.virtual~CLine();
25.virtualvoidSerialize(CArchive &ar);
26.CLine& operator=(CLine &src);
27.DECLARE_SERIAL(CLine);
28.};

实现文件:Line.cpp

001.//////////////////////////////////////////////////////////////////////
002.// Line.cpp: implementation of the CLine class.
003.//
004.//////////////////////////////////////////////////////////////////////
005. 
006.#include "stdafx.h"
007.#include "TestAdo.h"
008.#include "Line.h"
009. 
010.#ifdef _DEBUG
011.#undef THIS_FILE
012.staticcharTHIS_FILE[]=__FILE__;
013.#define new DEBUG_NEW
014.#endif
015. 
016.IMPLEMENT_SERIAL(CLine,CObject,1)
017. 
018.CLine::CLine()
019.{
020.Clear();
021.}
022.CLine::~CLine()
023.{
024. 
025.}
026.//重写 =
027.CLine& CLine::operator=(CLine &src)
028.{
029.if(this!=&src)
030.{
031.m_logPen = src.m_logPen;
032.m_crBackColor = src.m_crBackColor;
033.}
034.return*this;?
035.}
036.//串行化操作
037.voidCLine::Serialize(CArchive &ar)
038.{
039.if(ar.IsStoring())
040.{
041.ar <<DWORD(m_crBackColor);
042.ar.Write(&m_logPen,sizeof(LOGPEN));
043.}
044.else
045.{
046.DWORDdw;
047.ar >> dw; m_crBackColor =COLORREF(dw);
048.ar.Read(&m_logPen,sizeof(LOGPEN));
049.}
050.m_PointArray.Serialize(ar);
051.}
052. 
053.voidCLine::Clear()
054.{
055.m_crBackColor = RGB(255,255,255);
056.m_logPen.lopnStyle = PS_SOLID;
057.m_logPen.lopnWidth.x = 1;
058.m_logPen.lopnWidth.y = 1;
059.m_logPen.lopnColor = RGB(0, 0, 0);
060.m_PointArray.RemoveAll();
061.}
062.voidCLine::AddPoint(CPoint point)
063.{
064.m_PointArray.Add(point);
065.}
066. 
067.voidCLine::SetColor(COLORREFcolor)
068.{
069.m_logPen.lopnColor = color;
070.}
071.COLORREFCLine::GetColor()
072.{
073.returnm_logPen.lopnColor;
074.}
075.voidCLine::SetBkColor(COLORREFcolor)
076.{
077.m_crBackColor = color;
078.}
079.COLORREFCLine::GetBkColor()
080.{
081.returnm_crBackColor;
082.}
083.voidCLine::SetWidth(intiWidth)
084.{
085.m_logPen.lopnWidth.x = iWidth;
086.m_logPen.lopnWidth.y = iWidth;
087. 
088.}
089.//绘线条
090.voidCLine::DrawPoint(CDC *pDC, CRect rect)
091.{
092.intlen = m_PointArray.GetSize();
093.if(len <=0)return;
094.CPen pen;
095.pen.CreatePenIndirect(&m_logPen);
096.CPen *pOldPen = pDC->SelectObject(&pen);
097.CPoint pt = m_PointArray.GetAt(0);
098.pDC->MoveTo(pt);
099.for(inti=1; i< len; i++)
100.{
101.pt = m_PointArray.GetAt(i);
102.pDC->LineTo(pt);
103.}
104.pDC->SelectObject(pOldPen);
105.pOldPen = NULL;
106.pen.DeleteObject();
107.}
108. 
109.voidCLine::DrawBackGround(CDC *pDC, CRect rect)
110.{
111.CBrush brushCtl;
112.brushCtl.CreateSolidBrush(GetBkColor());
113.pDC->Rectangle(rect);
114.pDC->FillRect(rect,&brushCtl) ;
115.brushCtl.DeleteObject();
116.}
117.voidCLine::DrawLine(CDC *pDC,CPoint pt1, CPoint pt2, CRect rc)
118.{
119.CPen pen;
120.pen.CreatePenIndirect(&m_logPen);
121.CPen *pOldPen = pDC->SelectObject(&pen);
122.pDC->MoveTo(pt1);
123.pDC->LineTo(pt2);
124.pDC->SelectObject(pOldPen);
125.pOldPen = NULL;
126.pen.DeleteObject();
127.}
128.CPoint CLine::GetPoint(intpos)
129.{
130.if(pos>=0 && pos<m_PointArray.GetSize())?
131.{
132.returnm_PointArray.GetAt(pos);
133.}
134.returnCPoint(0,0);
135.}
136.intCLine::GetSize()
137.{
138.returnm_PointArray.GetSize();
139.}

二、用Ado接口打开数据库

01.BOOLCTestAdoDlg::OpenDb(CString filename)
02.{
03.HRESULThr=S_OK;
04.hr=m_pCon.CreateInstance("ADODB.Connection");
05.if(hr!=S_OK)
06.{
07.returnFALSE;
08.}
09.try
10.{
11._bstr_t sCon;
12.sCon=_bstr_t(filename);//路径名
13.sCon="Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+sCon;
14.hr=m_pCon->Open(sCon,"","",adModeUnknown);
15.if(hr!=S_OK)
16.{
17.returnFALSE;
18.}
19.///////////////////////
20.hr=m_pSet.CreateInstance("ADODB.Recordset");
21.if(hr!=S_OK)
22.{
23.returnFALSE;
24.}
25.m_pSet->CursorLocation=adUseClient;
26.hr=m_pSet->Open("SELECT * FROM object_table",_variant_t((IDispatch*)m_pCon,TRUE),
27.adOpenStatic,adLockOptimistic,adCmdText);
28.if(hr!=S_OK)
29.{
30.returnFALSE;
31.}
32.returnTRUE;
33.///////////////////////
34.}
35.catch(_com_error &e)
36.{
37.CString errorMessage;
38.errorMessage.Format("连接数据库失败!错误信息:%s",e.ErrorMessage());
39.returnFALSE;
40.}
41.returnFALSE;
42.}

(注意:在StdAfx.h中要加入:

1.#import "C:\Program Files\Common Files\SYSTEM\ADO\msado15.dll" no_namespace rename("EOF","adoEOF")

来引入ado库,还有在 BOOL CTestAdoApp::InitInstance() 加入 AfxOleInit();///初始化COM库)

三、CLine对象的保存

01.voidCTestAdoDlg::OnButtonSave()
02.{
03.//m_List
04.if(!m_bState)return;
05.UpdateData();
06.try
07.{
08.m_pSet->AddNew();
09.m_pSet->PutCollect("name", _variant_t(m_sName));
10. 
11.//保存图形对象
12.CMemFile memFile;
13.CArchive ar(&memFile, CArchive::store);
14.m_Line.Serialize(ar);
15.ar.Close();
16. 
17.DWORDdwSize = memFile.GetLength();
18.LPBYTElpInfo = memFile.Detach();
19. 
20.VARIANT varBLOB;
21.SAFEARRAY *psa;
22.SAFEARRAYBOUND rgsabound[1];
23. 
24.rgsabound[0].lLbound = 0;
25.rgsabound[0].cElements = dwSize;
26. 
27.psa = SafeArrayCreate(VT_UI1, 1, rgsabound);
28.for(longi = 0; i < (long)dwSize; i++)
29.{
30.SafeArrayPutElement (psa, &i, lpInfo++);
31.}
32.varBLOB.vt = VT_ARRAY | VT_UI1;
33.varBLOB.parray = psa;
34.m_pSet->GetFields()->GetItem("object")->AppendChunk(varBLOB);
35.m_pSet->Update();
36.m_List.AddString(m_sName);
37.}
38.catch(_com_error &e)
39.{
40.CString str=(char*)e.Description();
41.MessageBox(str+"\r保存数据库出问题!","提示",MB_OK|MB_ICONWARNING);
42.return;
43.}
44. 
45.}      

四、CLine对象的读取

view sourceprint?
01.voidCTestAdoDlg::OnSelchangeListData()
02.{
03.intiPos = m_List.GetCurSel();
04.if(iPos<0)return ;
05.m_pSet->MoveFirst();
06. 
07.inti=0;
08.while(i< iPos)
09.{
10.m_pSet->MoveNext();
11.i++;
12.}
13.longlDataSize = m_pSet->GetFields()->GetItem(_variant_t("object"))->ActualSize;
14.if(lDataSize <= 0)return;
15. 
16._variant_t varBLOB;
17.VariantInit (&varBLOB);
18. 
19.varBLOB = m_pSet->GetFields()->GetItem(_variant_t("object"))->GetChunk(lDataSize);
20.if(varBLOB.vt == (VT_ARRAY | VT_UI1))
21.{
22.BYTE*pBuf =new BYTE[lDataSize + 1];
23.if(pBuf)
24.{
25.SafeArrayAccessData(varBLOB.parray,(void**)&pBuf);
26.SafeArrayUnaccessData (varBLOB.parray);
27. 
28.CMemFile memfile;
29.memfile.Attach(pBuf,lDataSize);
30.memfile.SeekToBegin();
31.CArchive ar(&memfile, CArchive::load);
32. 
33.m_Line.Serialize(ar);
34.ar.Close();
35.memfile.Detach();
36.CRect rc = GetRect(IDC_STATIC_RECT);
37.InvalidateRect(rc);
38.}
39.}
40.VariantClear (&varBLOB);
41.}  


4.1 使用Boost库4.1.1 实现机制

这里,我们用术语序列化(serialization)来表示将一组原始的C++数据结构表示为字节流达到可逆析构的目的。这样的系统可以用来在另一个程序环境中重新建立原来的数据结构。因此,它也可以作为对象持久性(object persistence),远程参数传递(remote parameter passing),或者其他特性的实现基础。在我们的系统中,将使用术语档案(archive)表示一个具体的字节流。档案可以是二进制文件,文本文件,XML文件,或者其他用户定义的类型。   

Boost序列化库的目标是:

l  代码的可移植性–只依靠ANSI C++的特性。

l  代码的经济性–挖掘各种C++的特性如RTTI、模板、和多继承等等使用户容易使用并且代码短小。

l  类版本的独立性。–当一个类的定义改变时,老版本的类的档案仍然可以被导入新版本的类中。

l   指针的深度存储和恢复。–保存或恢复指针的同时保存或恢复指针指向的数据。

l  正确的处理多个指针指向相同对象时的问题。

l  对STL和其他常用模板类的序列化的直接支持。

l  数据的可移植性–在一个平台上建立的字节流在另一个平台上也应该是正确的。

l  序列化和档案格式的正交性–可以在不改变类的序列化部分时应用任何格式的文件作为档案。

l  支持非侵入(Non-intrusive)式的实现。类不需要从某个特定的类派生或者实现特定的成员函数。这对于我们不能或不愿意修改类的定义的情况时是相当必要的。

l  档案的接口应该足够简单使建立新类型的档案的工作变得轻松。

l  档案应该支持XML格式。

   Boost中,与序列化有关的两个库是Archive库和Serialization库。

4.1.2 实现步骤

首先,为被序列化的类实现一个对应的serialize(Archive & ar, const unsigned int version)方法;

其次,构造boost::archive::text_oarchive类或其他archive输出类的对象,并将其关联到一个输出流,利用<<运算符将被序列化的对象输出到某个文档中;

最后,构造boost::archive::text_iarchive类或其他archive输入类的对象,并将其关联到一个输入流,读入数据,利用>>运算符会付出被序列化的对象。

4.1.3 注意事项

使用这种方法需要注意的是:

l  Boost从1.32版本之后才提供对序列化的支持,所以一定要用版本在1.32之后的;

l  Boost中的Serialization库需要编译之后得到库文件才能使用,并加入项目的附加依赖项中才可使用;

l  根据需要包含boost/serialization和boost/archive下的一些头文件。

4.2 使用.NET4.2.1 实现机制

.NET的运行时环境用来支持用户定义类型的流化的机制。它在此过程中,先将对象的公共字段和私有字段以及类的名称(包括类所在的程序集)转换为字节流,然后再把字节流写入数据流。在随后对对象进行反序列化时,将创建出与原对象完全相同的副本。

.Net框架对序列化机制具有非常好的支持,它提供了两个名字空间(namespace):System.Runtime.Serialization和System.Runtime.Serialization.Formatters以完成序列化机制的大部分功能。

序列化机制的实现是依靠格式器(Formatter)而完成的,它是一个从System.Runtime.Serialization.IFormatter继承下来的类的对象。格式器完成了将程序数据转化到能被存储并传输的格式的工作,同时也完成了将数据转化回来的工作。.Net框架为程序员提供了两种类型的格式器,一种通常是应用于桌面类型的应用程序的,它一个是System.Runtime.Serialization.Formatters.Binary.BinaryFormatter类的对象,而另一种则更主要的应用于.Net Remoting和XML Web服务等领域的,它一个是System.Runtime.Serialization.Formatters.Soap.SoapFormatter类的对象。从它们的名称来看,不妨将它们分别称为二进制格式器和XML格式器。它们对应于.Net提供的两种序列化技术:

二进制序列化保持类型保真度,这对于在应用程序的不同调用之间保留对象的状态很有用。例如,通过将对象序列化到剪贴板,可在不同的应用程序之间共享对象,可以将对象序列化到流、磁盘、内存和网络等等。它的优点在于可以将所有的对象成员都保存下来,并且性能优于XML序列化。

XML 序列化仅序列化公共属性和字段,且不保持类型保真度。当您要提供或使用数据而不限制使用该数据的应用程序时,这一点是很有用的。由于 XML 是一个开放式标准,因此,对于通过 Web 共享数据而言,这是一个很好的选择。SOAP 同样是一个开放式标准,这使它也成为一个颇具吸引力的选择。它的优点在于互操作性好,可读性强。

4.2.2 实现步骤

使用.Net下的二进制序列化方法进行对象序列化的步骤如下:

首先,要使用 Serializable 属性对对象的类进行标记;

其次,利用BinaryFormatter的Serialize方法将对象写入到一个文件流中;

最后,利用BinaryFormatter的DeSerialize方法读取文件流,恢复对象。

4.2.3 注意事项

使用这种方法需要注意的是:

l  需要使用System::Runtime::Serialization::Formatters::Binary命名空间和 System::Runtime::Serialization命名空间;

l  被序列化的类在声明时必须标识[Serializable]属性;

l  所涉及的类必须是托管类,即类的声明前需要有ref关键字,用gcnew关键字表示在托管堆上分配内存,指针符号用^来标识等。

4.3 使用MFC4.3.1 实现机制

对象的序列化归根结底是将对象的数据写入载体,再重新读取为对象的过程。MFC中对数据的读写创造了十分好的支持,这使得我们可以十分方便的利用MFC的数据读写类来实现对象序列化的需要。

MFC 为数据读写设计了三个基本的类——CFile(CFile类)、CStdioFile(标准I/O文件类)、CArchive(CArchive类)。其中标准CStdioFile类提供相当于C的流式文件的功能,可以用文本或者二进制方式打开,可以被缓冲。CFile类提供了非缓冲的二进制输入输出文件,它既可以与CArchive类结合实现VisualC++设计中常用的文件序列化,也可以由设计者自己订制存储方案,实现数据的读写操作(此方法的兼容问题需要解决,保密性强)。CArchive类是VisualC++程序设计中最常用的文件处理的方法,CArchive类不仅可以实现简单数据结构的读写操作,还可以通过对CObiect类的派生实现对复杂数据结构的读写操作,因此,利用CArchive类,可以轻松实现任意数据结构的序列化。

4.3.2 实现步骤

实现序列化的的类需要满足一系列条件:

1. 该类需要从CObject类派生(可以是间接派生);

2. 在类中中进行DECLARE_SERIAL宏定义;

3. 类存在有缺省的构造函数;

4. 类中实现了Serialize(CArchive&)函数,并且在其中调用基类的序列化函数;

5. 使用IMPLEMENT_SERIAL宏指明类名及版本号。

满足了这些条件之后,就可以进行序列化与反序列化了。

序列化时,首先,实例化一个CArchive类的对象,将其与输出文件相关联;其次,利用CArchive类的<<运算符重载将需要序列化的对象保存在文件中。

反序列化时,将CArchive类的对象与保存对象的文件相关联;然后新建一个需要反序列化的对象,利用CArchive类的>>运算符重载将文件里的内容恢复到需要反序列化的对象中。

4.3.3 注意事项

使用这种方法需要注意的是:

l  需要包含afx.h头文件;

l  它不支持string类型的序列化,但是支持CString类型的序列化;

l  需要将项目属性中的MFC属性配置为“在共享DLL中使用MFC”或“在静态库中使用MFC”,否则编译时会报错。

5 使用Boost库进行对象序列化的关键技术5.1 基础

1、基本类型的存档和读取

对基本类型. 直接使用以下语句就可以完成存档或读取:

l  用 ar << data或ar & data;  写入存档

l  用 ar >> data或ar & data;  从存档取出

2、自定义类型的存档和读取

对自定义类型. 则会调用 serialize() 函数,serialize 函数用来“存储/装载”其数据成员。这个处理采用递归的方式,直到所有包含在类中的数据“被存储/被装载”。

l  侵入式:  t.serialize(ar, version)

l  非侵入式:  serialize(ar, t, version)

3、所需包含的头文件:

l  以简单文本格式实现存档:text_oarchive和text_iarchive

l  宽字符的文本格式存档 :text_woarchive  text_wiarchive

l  xml存档:xml_oarchive  xml_iarchive

l   使用宽字符的xml文档(用于utf-8)输出:xml_woarchive    xml_wiarchive

l  二进制的存档 (注意 二进制存档是不可移植的):binary_oarchive   binary_iarchive

5.2 侵入式和非侵入式

对于被序列化的类,有两种实现其对应的serialize方法的方式,一种是侵入式,即把serialize方法作为被序列化类的一个成员方法来实现;另一种是非侵入式,即将serialize方法放在另一个名字空间下,作为被序列化类的一个友元方法来实现。在不可修改被序列化的类的代码的情况下,应该采用非侵入式的方式。

侵入式的例子:

class MyPoint

{

    int mX;
    int mY;

private:
    friend class  boost::serialization::access;   //侵入式版本的要加这个.

    //存入和读取都使用下边的 serialize() 函数.
    //其中的 Archive 是一个输入或输出的文档.  当输入的时候 & 为 >> . 当输出的时候 & 为 <<.
    template<class Archive>
    void serialize(Archive& ar, const unsigned int version)
    {
        ar & mX;       //序列化数据成员
        ar & mY;
    }

public:
    MyPoint() {}
    MyPoint(int x, int y) : mX(x), mY(y) {}   
};

非侵入式的例子:

class MyPoint
{
private:         

// 注意关键字”friend”和多了一个类引用作参数

     template<class Archive>

friend void serialize(Archive& ar, MyPoint&, unsigned int const);

    int mX;
    int mY;
public:
    MyPoint() {}
    MyPoint(int x, int y) : mX(x), mY(y) {}
};
//非侵入式
namespace boost {                  //实现放在这个名字空间下
namespace serialization {

template<class Archive>
void serialize(Archive & ar, MyPoint& p, const usigned int version)
{
    ar & p.mX & p.mY;   //可以连着 &
}

}
}   //namespace  结束

5.3 派生类的序列化

对派生类进行序列化需要有一个前提,即它的父类必须也实现了serialize方法,也可以序列化。如果在派生类的父类没有实现serialize方法,仅对派生类进行序列化,将不能保存派生类从父类继承下来的数据信息,而仅能保存属于派生类自身的数据信息。

对派生类进行序列化的步骤是:

1、包含boost/serialization/base_object.hpp头文件;

2、在serialize模版方法中,使用ar & boost::serialization::base_object<父类>(*this)这样的语法来保存父类的数据,不能直接调用父类的serialize函数。

一个例子如下:

#include <boost/serialization/base_object.hpp> //一定要包含此头文件

class B:A

{

    friend class boost::serialization::access;

    char c;

    template<class Archive>

    void serialize(Archive & ar, const unsigned int version)

    {

        ar & boost::serialization::base_object<A>(*this);//注意这里

        ar & c;

    }

public:

    …

};   

5.4 数组的序列化

对于数组进行序列化,就是保存数组中的每一个数据成员,因此相当于对数组中的每一个数据成员做序列化。可以用以下形式:

for(int i = 0; i < sizeof(array); i++)

{

  ar & array[i];

}

但是事实上,Boost的序列化库能检测出被序列化的对象是一个数组,将产生上述等价的代码,例子如下:

class bus_route

{

    friend class boost::serialization::access;

    bus_stop stops[10];

    template<class Archive>

    void serialize(Archive & ar, const unsigned int version)

    {

        ar & stops;

    }

public:

    bus_route(){}

};

5.5 指针的序列化

序列化整个对象是要求在另一个地方和时间重新构造原始数据结构。在使用指针的情况下,为了达到重新构造原始数据结构的目的,仅仅存储指针的值是不够的,指针指向的对象也必须被存储。当成员最后被装载,一个新的对象被创建,指向新的对象的新的指针被装载到类的成员中。

所有这一切由Boost的序列化库自动完成,程序员只需直接序列化指针即可。(说是这么说,使用要慎重,因为例子并没有调通。)一个例子如下:

class bus_route{    friend class boost::serialization::access;    bus_stop * stops[10];    template<class Archive>    void serialize(Archive & ar, const unsigned int version)    {        int i;        for(i = 0; i < 10; ++i)            ar & stops[i];    }public:    bus_route(){}};5.6 对STL容器的序列化

对于STL容器,比如vector或list,需要在头文件中包含<boost/serialization/vector.hpp>或<boost/serialization/list.hpp>等,然后就可以直接进行序列化了。一个例子如下:

#include <boost/serialization/list.hpp>class bus_route{    friend class boost::serialization::access;    std::list<bus_stop *> stops;    template<class Archive>    void serialize(Archive & ar, const unsigned int version)    {        ar & stops;    }public:    bus_route(){}};5.7 被序列化的类的成员是其他类的对象的情况

如果被序列化的类有成员是其他类的对象,那么,只有在其对象成员的类也实现了serialize方法并能被序列化的情况下,该类才能被序列化。

比如前几个例子中,类bus_route中有成员是bus_stop类的对象。那么只有bus_stop类实现了serialize方法后,bus_route类才能被序列化。

5.8 输出

Boost的序列化库可以以三种格式进行输出,分别是:简单文本格式、XML格式,以及二进制格式。其中每种格式又可以输出到c++的ostream流中,比如,ostringstream(字符串输出流),ofstream(文件输出流)。下例是一个以简单文本格式输出到字符串流中的例子。

//序列化,输出到字符串

         std::ostringstream ossOut(ostringstream::out);   //把对象写到字符串输出流中

         boost::archive::text_oarchive oa(ossOut);

         TestClass objTestClass;

oa << objTestClass;

string strTrans = ossOut.str();

……

//反序列化,从字符串输入

istringstream ossIn(strTrans);      //从字符串输入流中读入数据

         boost::archive::text_iarchive ia(ossIn);

         TestClass newObjTestClass;

         ia >> newObjTestClass;

6 结论

1、  在基于OTT结构的数据库结构的性能测试中,针对数据库中的每一个表,定义了一个相应的类,我们的目标是将这些类的对象进行序列化。但是,在试图序列化的过程中遇到一个问题,即:所有的OTT表的类都继承自一个由Oracle库文件定义的类oracle::occi::PObject。而派生类的序列化要求其父类也必须实现序列化接口,否则就会派生类继承的父类的成员就会在序列化时丢失(见5.3节)。这就要求修改库文件,是PObject也实现序列化接口。可是贸然地修改库文件可能会导致连锁反应,引起其他引用库文件的程序出错,此外,还有知识产权的问题。所以,使用Boost序列化库来对OTT表的类进行序列化的路可能走不通。应考虑其他方法。

2、  在使用共享内存传递对象数据时,可以将对象数据以简单文本格式进行序列化,再用ostringstream流输出到字符串中,进行传递,完全可行。

7 附录7.1 资源

1、Boost中Serialization库的文档:http://www.boost.org/doc/libs/1_37_0/libs/serialization/doc/index.html;

2、Boost序列化库教程:http://dozb.bokee.com/1692310.html#derivedclasses;

3、Learning boost 1 Serialization:http://blog.csdn.net/freerock/archive/2007/08/17/1747928.aspx

4、 C++中使用boost::serialization库――应用篇:http://www.cnblogs.com/mslk/archive/2005/11/25/284491.html;

5、 C++ Reference: IOstream Library: ostream:http://www.cplusplus.com/reference/iostream/ostream/;

7.2 程序示例对照表

l  CplusSerializeBoost:使用Boost的序列化库进行序列化;

l  CplusSerializeDotNet:使用.Net进行序列化;

l  CplusSerializeMFC:使用MFC进行序列化。


原创粉丝点击