现在开始做序列化的读,也即是反序列化,本来为没个序列化的类设计了2个序列化接口函数:
//序列化接口
virtual void GetObjectData(CJSerializationInfo* info) {}
virtual void DeSerializationObjectData(CJSerializationInfo* info) {}
可突然发现,其实DeSerializationObjectData是没必要存在的,在.net中,每个对象都是引用,所以它可以为每个对象创建新的实例,然后再赋值,可C++中不可以啊,因为我有些对象包括上层类的实例中,它已经不需要再去实例化了。,所以在反序列化的时候,很多对象不能直接new,而必须从宿主对象中获取。只有哪些动态生成的对象才可以new。
中心思想有了,开始实现吧。
首先定义对象读取类
class CObjectRead
{
public:
class ObjectMemberValue
{
public:
juint32 TypeID;
juint32 Valuetypeid;
CJObject* pValue;
};
CObjectRead(CSerialization* pSer,jint32 id,CJStream* pStream);
void Read(jbyte headercode);
CJSerializationInfo* ReadObjectSerializationInfos();
void ReadPrimitive(CJSerializationInfo* pSerInfo,CJSerializationInfo* currentObjSInfo,int index,jbyte typecode);
public:
CSerialization* m_pSerialization;
CJObject* m_pObj;
CJObject* m_pParentObj;
CJStream* m_pStream;
jint32 m_ObjID;
CJList m_ObjectMemberValues;
};
它的基本作用就是读取一个对象,并把它放到对象实例映射 表中去(在CSerialization对象中),具体过程:
反序列化入口函数:CSerialization的DeSerialize
CJObject* CSerialization::DeSerialize(CJStream* pStream)
{
jint32 head;
CJObject* pTopObj = JNULL;
if(!pStream->ReadInt32(&head))return JNULL;
if(head != 0xFF78FF78)return JNULL;
char c;
pStream->ReadChar(&c);if(c != 'J')return JNULL;
pStream->ReadChar(&c);if(c != 'H')return JNULL;
pStream->ReadChar(&c);if(c != 'M')return JNULL;
pStream->ReadChar(&c);if(c != 'F')return JNULL;
//确认是我们的序列化数据
jbool readend = FALSE;
jbyte headtype;
while(pStream->ReadByte(&headtype))
{
switch(headtype)
{
case SER_HRADERTYPE_OBJINFO:
{
CObjectRead obread(this,-1,pStream);
AddObjectSerializationInfos(obread.ReadObjectSerializationInfos());
}
break;
case SER_HRADERTYPE_BASEDATA:
case SER_HRADERTYPE_ARRAY:
case SER_HRADERTYPE_OBJHEADER:
{
CObjectRead obread(this,-1,pStream);
obread.Read(headtype);
}
break;
case SER_HRADERTYPE_END:
readend = TRUE;
goto DeSerializeEnd;
break;
default:
if(headtype >= SER_HRADERTYPE_OBJMEMBER && headtype <= SER_HRADERTYPE_String)
{
}
else
{
JThrowSerialException("序列化数据被破坏");
}
break;
}
}
DeSerializeEnd:
if(readend)
{
CHasReadedObject* pTopReadObj = GetHasReadedObject(topID);
JASSERT(pTopReadObj != JNULL);
pTopObj = pTopReadObj->m_pObject;
//修复所有对象
CJListT* keys = this->m_FixingObjects.GetKeys();
for(int i = 0;i < keys->GetCount();i++)
{
CHasReadedObject* pReadObj = (CHasReadedObject*)m_FixingObjects.GetHashObject(0,(*keys)[i]);
JASSERT(pReadObj != JNULL && pReadObj->m_pObject != JNULL);
if(pReadObj->m_pObject->GetType().IsArray())
{
//指针数组需要特殊处理
CJObjectArray* pArray = (CJObjectArray*)pReadObj->m_pObject;
for(int j = 0;j < pArray->GetLength();j++)
{
CJObject* pitem = pArray->GetItem(j);
if(pitem->GetType() == JTYPEOF(CFixObject))
{
CFixObject* pfix = (CFixObject*)pitem;
CHasReadedObject* preaded = GetHasReadedObject(pfix->m_ObjectID);
JASSERT(preaded != JNULL);
pArray->SetItem(preaded->m_pObject,j);
delete pitem;
}
}
}
else
{
//首先获取序列化信息
CJSerializationInfo* currentObjSInfo = GetCurrentObjectSerializationInfos(pReadObj->m_typeID,pReadObj->m_pObject);
JASSERT(currentObjSInfo != JNULL);
for(int i = 0;i < currentObjSInfo->GetStatisticsCount();i++)
{
if(((SerializationInfoField*)currentObjSInfo->m_fields[i])->fieldTypeID == FIELDTYPE_OBJPTR)
{
CJObject** pfObj = (CJObject**)currentObjSInfo->GetFieldObject(pReadObj->m_pObject,i);
if(pfObj == JNULL)continue;
if(*pfObj == JNULL)continue;
if((*pfObj)->GetType() == JTYPEOF(CFixObject))
{
//修复引用
CFixObject* pfix = (CFixObject*)*pfObj;
CHasReadedObject* preaded = GetHasReadedObject(pfix->m_ObjectID);
JASSERT(preaded == JNULL);
*pfObj = preaded->m_pObject;
delete pfix;
}
}
}
}
}
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&资源清除&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//删除当前库类型序列化信息
//删除文件库类型序列化信息
//删除读取对象实例映射表
return pTopObj;
}
这个函数目的很简单,首先做格式判断,然后开始一个一个的读取对象(和对象序列化格式信息),真正读取对象:
void CObjectRead::Read(jbyte headercode)
{
jint64 ll = m_pStream->GetPosition();
jint32 typeID,id,parentid,findex;
if(!m_pStream->ReadInt32(&typeID))JThrowSerialException("序列化数据被破坏");
if(!m_pStream->ReadInt32(&id))JThrowSerialException("序列化数据被破坏");
if(!m_pStream->ReadInt32(&parentid))JThrowSerialException("序列化数据被破坏");
if(!m_pStream->ReadInt32(&findex))JThrowSerialException("序列化数据被破坏");
//根据类型ID此时可以确认对象类型了,而且对象类型信息应该已经存在于映射表中了
CJSerializationInfo* pObSerInfos = m_pSerialization->GetObjectSerializationInfos(typeID);
if(pObSerInfos == JNULL)JThrowSerialException("序列化内核异常:对象类型信息丢失,数据被破坏");
//此时比较复杂,处理需反复斟酌
if(parentid > 0)
{
//有父对象,此时,父对象已经产生,从父对象中获取实例
CHasReadedObject* pParentObj = m_pSerialization->GetHasReadedObject(parentid);
if(pParentObj == JNULL || pParentObj->m_pObject == JNULL)JThrowSerialException("序列化内核错误:无法找到父对象");
CJSerializationInfo* parentSinfo = m_pSerialization->GetObjectSerializationInfos(pParentObj->m_typeID);
if(parentSinfo == JNULL)JThrowSerialException("序列化内核错误:无法找到父对象序列化信息(此时程序应该已经保证父对象类型序列化信息已经被读取)");
CJSerializationInfo* currentParentSInfo = m_pSerialization->GetCurrentObjectSerializationInfos(pParentObj->m_typeID,pParentObj->m_pObject);
m_pObj = currentParentSInfo->GetFieldObject(pParentObj->m_pObject,parentSinfo->GetFieldInfo(findex)->name);
if(m_pObj == JNULL)
{
//有父对象,但确找不到自己的实例,唯一的可能是版本不一致,用户程序去除了该字段的序列化
}
}
else
{
//创建该对象
CJObject* pnewObj = CJActivator::CreateInstance(pObSerInfos->m_Name);
//需要做外部实例化处理,现在不做,待续
if(pnewObj == JNULL)JThrowSerialException(CJString::FormatString("序列化异常:无法创建%s对象",pObSerInfos->m_Name));
m_pObj = pnewObj;
}
CHasReadedObject* pObjRead = m_pSerialization->AddReadedInstances(m_pObj,typeID,id,parentid);
if(headercode == SER_HRADERTYPE_OBJHEADER)
{
//增加到对象映射表
CJSerializationInfo* currentObjSInfo = m_pSerialization->GetCurrentObjectSerializationInfos(typeID,m_pObj);
jbool objectconplete = TRUE;
//开始读取成员
if(pObSerInfos->GetStatisticsCount() > 0)
{
//强制性初始化,将对象中的参与反序列化的引用(指针)初始化为空
if(m_pObj != JNULL)
{
for(int i = 0;i < currentObjSInfo->GetStatisticsCount();i++)
{
if(((SerializationInfoField*)currentObjSInfo->m_fields[i])->fieldTypeID == FIELDTYPE_OBJPTR)
{
CJObject** pfObj = (CJObject**)currentObjSInfo->GetFieldObject(m_pObj,i);
if(pfObj == JNULL)continue;
*pfObj = JNULL;
}
}
}
jbyte membetype;
for(int i = 0;i < pObSerInfos->GetStatisticsCount();i++)
{
jint64 ll1 = m_pStream->GetPosition();
if(!m_pStream->ReadByte(&membetype))JThrowSerialException("序列化内核异常:对象成员读取失败,数据被破坏");
while(membetype == SER_HRADERTYPE_OBJINFO)
{
m_pSerialization->AddObjectSerializationInfos(ReadObjectSerializationInfos());
if(!m_pStream->ReadByte(&membetype))JThrowSerialException("序列化内核异常:对象成员读取失败,数据被破坏");
}
switch(membetype)
{
case SER_HRADERTYPE_OBJMEMBER:
{
//对象,该对象存储在其他地方,此时,该对象已经被实例化了
}
break;
case SER_HRADERTYPE_OBJMEMBERPTR:
{
jint32 memberid,memberindex;
m_pStream->ReadInt32(&memberid);
m_pStream->ReadInt32(&memberindex);
if(m_pObj != JNULL)
{
CJObject* pMemberObj = JNULL;
pMemberObj = currentObjSInfo->GetFieldObject(m_pObj,pObSerInfos->GetFieldInfo(memberindex)->name);
if(pMemberObj != JNULL)
{
CJObject** ppMemberObj = (CJObject**)pMemberObj;
CHasReadedObject* pReadedMembetObj= m_pSerialization->GetHasReadedObject(memberid);
if(pReadedMembetObj != JNULL)
{
//如果对象已经存在
*ppMemberObj = pReadedMembetObj->m_pObject;
}
else
{
CFixObject* fixObj = new CFixObject();
fixObj->m_ObjectID = memberid;
*ppMemberObj = fixObj;
//增加到待修复队列
if(objectconplete)
{
m_pSerialization->AddToFix(pObjRead);
}
objectconplete = FALSE;
}
}//确定该字段存在
}//确定该对象实例存在
}
break;
default:
if(membetype >= SER_HRADERTYPE_Boolean && membetype <= SER_HRADERTYPE_String)
{
ReadPrimitive(pObSerInfos,currentObjSInfo,i,membetype);
}
else
{
JThrowSerialException("序列化异常:不识别的头类型");
}
break;
}
}
}
}
else if(headercode == SER_HRADERTYPE_ARRAY)
{
CJObjectArray* pArray = (CJObjectArray*)m_pObj;
jint32 length;
if(!m_pStream->ReadInt32(&length))JThrowSerialException("序列化数据被破坏");
if(length > 0)
{
for(int i = 0;i < length;i++)
{
jint32 id;
if(!m_pStream->ReadInt32(&id))JThrowSerialException("序列化数据被破坏");
if(pArray == JNULL)continue;
CFixObject* fixObj = new CFixObject();
fixObj->m_ObjectID = id;
pArray->AddItem(fixObj);
}
if(m_pObj != JNULL)
{
m_pSerialization->AddToFix(pObjRead);
}
}
}
else if(headercode == SER_HRADERTYPE_BASEDATA)
{
CJBaseDataType* pBaseObj = (CJBaseDataType*)m_pObj;
jbool bnew = FALSE;
if(pBaseObj == JNULL)
{
//也许该对象不存在,也许该字段不存在了,此时读取,只为兼容格式,不保存信息
pBaseObj = (CJBaseDataType*)CJActivator::CreateInstance(pObSerInfos->m_Name);
if(pBaseObj == JNULL)JThrowSerialException(CJString::FormatString("序列化异常:无法创建%s对象",pObSerInfos->m_Name));
bnew = TRUE;
}
CJArchive ar(m_pStream);
pBaseObj->DeSerialize(&ar);
if(bnew)
{
CJActivator::ReleaseInstance(pBaseObj);
}
}
else
{
JThrowSerialException("序列化异常:不识别的对象类型头");
}
}
这个函数有点长了,看注释基本上可以明白内容,看看读取对象序列化类型信息
CJSerializationInfo* CObjectRead::ReadObjectSerializationInfos()
{
CJSerializationInfo* pObjSerinfos = new CJSerializationInfo();
jint32 fieldcount;
if(!m_pStream->ReadString(&pObjSerinfos->m_Name))JThrowSerialException("序列化数据被破坏");
if(!m_pStream->ReadInt32(&pObjSerinfos->m_typeID))JThrowSerialException("序列化数据被破坏");
if(!m_pStream->ReadInt32(&fieldcount))JThrowSerialException("序列化数据被破坏");
if(fieldcount > 0)
{
for(int i = 0;i < fieldcount;i++)
{
SerializationInfoField* field = new SerializationInfoField;
m_pStream->ReadUInt32(&field->fieldTypeID);
m_pStream->ReadUInt32(&field->valuetypeid);
m_pStream->ReadString(&field->name);
pObjSerinfos->m_fields.Add(field);
}
}
return pObjSerinfos;
}
对于CJSerializationInfo对象,我们有2个,一个是从文件(二进制)中获取,一个是从程序中调用对象的GetObjectData获取,
为什么会有2个呢,因为他们可能不一致,所以在读取的时候是以文件(二进制)中保存的信息为准,而在赋值的时候是以GetObjectData获取的为准,这样可以解决版本兼容问题,而且反序列化程序不会因为格式变换而乱。
以上工作,基本上完成了序列化所有主要的工作,其他工作(如资源释放等)以后做.下次要开始调试,测试工作了。
阅读(939) | 评论(0) | 转发(0) |