具体实施方式
下面结合附图和具体实施例对本发明进行详细说明。
图1为根据本发明实施例的一种存储数据的方法的流程图。如图1所示,该方法包括:
步骤101:建立至少包括第一节点的自定义数据结构。
在本步骤中,该第一节点为根节点。每个节点包括第一模块,用于存储数据的类型标识和值,以及第二模块用于存储该节点的子节点的标识与子结点之间的映射列表。
为了描述方便,本发明将这种自定义数据结构定义的数据类型称为通用数据类型(WData)。
步骤102:每接收一个数据判断数据将要存储的位置以及数据的类型。
本步骤中,当用户为具有自定义数据结构的变量赋值时,则自定义数据结构接收到数据。在此,用户为变量赋值相当于将数据存储于该变量中;数据的类型可以是任何的基本类型,比如整型(int),浮点型(float),字节型(byte)等。
步骤103:如果数据存储于第一节点,则将数据的类型以及数据的值存储在第一节点的第一模块中。
本步骤中,当数据存储于第一节点,即存储于根节点时,该根节点无需对应一个节点标识与节点之间的映射列表,即<key,WData节点>(以下简称<key,WData>)。并且,当自定义数据结构中仅有第一节点,则第一节点中的第二模块的映射列表为空。当第一节点存在子节点时,则第一节点中的第二模块的映射列表记录第一节点的子节点标识与子节点之间的映射列表<key,WData>。
步骤104:如果数据存储于自定义数据结构的其他节点(称为第二节点),则将数据的类型以及数据的值存储在第二节点的第一模块中。
本步骤中,当数据存储于第二节点时,由于第二节点为子节点,则该数据属于子数据。此时,第二节点对应一个节点标识与节点之间的映射列表,比如<key2,WData>。该映射列表存储于第二节点的父节点中,用于索引第二节点的子节点,从而索引子结点中的数据。
在步骤104之前,还包括:判断自定义数据结构中是否包括第二节点;如果没有,则建立所述自定义数据结构的第二节点;否则,直接将数据的类型以及数据的值存储在所述第二节点的第一模块中。
建立自定义数据结构的第二节点可以包括:在第二节点的父节点的第二模块中填写第二节点的标识与第二节点之间的映射列表。
同理,当接收到存储于第二节点的子节点的数据时,在第二节点中的第二模块填写子节点的标识与子节点之间的映射列表。
以上的自定义数据结构可以由C++语言、或脚本语言或VB语言等来实现。
由以上实施例可以看出,由于自定义数据结构定义了一种通用数据类型;当将数据存储为该通用数据类型时,该通用数据类型可以判断待存储数据的类型,并将待存储数据的类型和值进行存储。因而,用户在存储数据时,不用手动进行不同数据类型的转换。
而且,由于在一个自定义数据结构的通用数据类型中,每个节点都可以设有其子节点的<key,WData>映射列表,因此,可以将大量的数据存储于该通用数据类型中。这种情况下,只要将大量的数据存储成一个通用数据类型,则可以在传递一个通用数据类型的变量的情况下传递大量的数据,从而可以大大简化通讯系统的构建和维护。
图2为本发明实施例中存储数据的存储模型,即示出了自定义数据结构中每个节点的存储模型。如图2所示,每个存储模型至少存储一个WData数据,其包括第一模块(Value模块),用于存储WData数据的类型标识和值,以及第二模块(<key,WData>模块),用于存储该节点的子节点的标识与子节点之间的映射列表<key,WData>。在第二模块中,key可以使用字符串表示。
通过以上的存储模型,通用数据类型WData可以构造成一个树状的通用数据类型。
根据本发明实施例,上述的第一模块可以利于VARIANT结构来实现数据的类型标识和值的存储。具体地,VARIANT结构的内部利用一个类型标识来表示具体的数据类型。当需要使用存储的数据时,可以根据VARIANT结构中的类型标识来判断数据的类型,然后获取存储的数据。
VARIANT结构的定义如下:
struct tagVARIANT
{
union
{
struct_tagVARIANT
{
VARTYPE vt;//类型标识
WORD wReserved1;
WORD wReserved2;
WORD wReserved3;
//以下为具体的类型,每次只有一个有效
//具体根据类型标识来判断哪个类型有效
union
{
LONG lVal;
BYTE bVal;
SHORT iVal;
FLOAT fltVal;
......
}
......
}
......
在定义VARIANT结构后,则可以按照上述结构存储数据。在存储数据后,则可以使用存储的数据。
图3示出了本发明实施例中存储数据的通用数据类型的树状结构。如图3所示,第一节点(根节点)可以有一个或多个子节点,而每个子节点也可以有一个或多个子节点,依此类从。这种情况下,一个通用数据类型的变量可以存储大量的数据。并且,由于<key,WData>这种映射关系的使用,可以很方便地读取各个存储的数据,并可以方便地改变存储的某个或某些数据的数据类型或数据值。图3中,第一节点的第一模块存储自身的一个值,以及该值的类型标识,第二模块中存储的<key,WData>列表包括5个映射关系,即(key1,WData),(key2,WData),(key3,WData),(key4,WData)和(key5,WData)。其中,(key3,WData)对应的节点的第二模块中又存储有包括2个映射关系的<key,WData>列表,即(key6,WData)和(key7,WData);而(key4,WData)对应的节点的第二模块中又存储有包括一个映射关系的<key,WData>列表,即(key8,WData)。
由此可见,本发明实施例提出的存储模型是一种递归的存储方式,可以构成树状的通用数据类型,存储大量的数据。
图3所示的树状结构只是本发明的通用数据类型的一种结构,并不用于限制本发明通用数据类型的结构。本发明的通用数据类型还可以由嵌套结构等具有多级索引特性的其他结构来实现。
在通过图2和3所示的通用数据类型定义了一个变量之后,则可以方便地利用该变量对数据进行操作,比如对数据进行读取、转换以及传递。
图1所示的存储数据的方法可以实现不同类型的数据在同一变量中的存储,并且可以实现大量的数据的多级存储,比如图3所示的树状存储。在以下实施例中,以C++语言的系统为例并结合图3所示的树状结构,说明本发明实施例中数据存储方法。
在C++语言中,定义一个通用数据类型以及将数据存储在通用数据类型如下所示:
WData data;data=5;data=”xxx”;
data[“key1”]=10;data[“key1”]=”sss”;
data[“key3”][“key6”]=15;
data[“key3”][“key6”][...][...]...=...
从以上可以看出,首先定义了一个通用数据类型的变量data。其次,则可以对变量data进行赋值,即可以在data中存储数据。在本实施例中,给data赋值整型数据“5”;再次,还可以给data赋值字符串数据“xxx”,即将字符串数据“xxx”存储到WData通用数据类型的变量data中,覆盖了之前存储的整型数据“5”。具体地,可以通过重载“=”操作符的方式实现将数据“5”或“xxx”存储在变量data的根节点的第一模块中(即Value模块中)。
除了将数据存储在根节点外,还可以进行多级存储,即可以在根节点的子节点存储数据。例如,在key1对应的子节点中存储整型数据10或字符串数据“sss”。再例如,在key3对应的子节点中的key6对应的子节点中存储整型数据15。通过以上的存储方法,可以将大量的不同类型的数据存储在一个通用数据类型的变量中,从而可以方便数据的使用。在多级存储中,可以重载[]操作符来实现key与各个WData的映射。
在采用图1所示的方法存储数据之后,则可以方便地使用存储的数据,比如读取、转换以及传递等。以下将结合存储数据的装置来说明如何使用存储的数据。
图4为本发明实施例的一种存储数据的装置。如图4所示,该装置包括:
数据接口401,用于接收数据;
通用数据类型组件402,用于建立并存储至少包括作为根节点的第一节点的自定义数据结构,其中,每个节点包括第一模块,用于存储数据的类型标识和值,以及第二模块用于存储所述节点的子节点的标识与子节点之间的映射列表;每当数据接口401接收一个数据,用于判断数据将要存储的位置以及数据的类型;如果数据存储于第一节点,则将数据的类型以及数据的值存储在第一节点的第一模块中;如果数据存储于自定义数据结构中的第二节点,将数据的类型以及数据的值存储在第二节点的第一模块中。
根据本发明实施例,通用数据类型组件包括:节点建立模块,判断模块和存储模块;
节点建立模块,用于建立并保存至少包括作为根节点的第一节点的自定义数据结构;
判断模块,用于判断数据的存储于第一节点或第二节点以及数据的类型,并将判断结果通知给存储模块;
存储模块,用于根据判断模块的判断结果,将数据的类型以及数据的值存储在所述第一节点的第一模块中或将数据的类型以及数据的值存储在第二节点的第一模块中。
根据本发明实施例,判断模块还用于在数据存储于所述自定义数据结构的第二节点时,判断自定义数据结构中是否包括第二节点;如果没有,则通知节点建立模块建立自定义数据结构的第二节点;否则,通知存储模块将数据的类型以及数据的值存储在第二节点的第一模块中。
根据本发明实施例,节点建立模块通过在第二节点的父节点的第二模块中填写第二节点的标识与第二节点之间的映射列表来建立第二节点。
根据本发明实施例,数据接口还用于从通用数据类型组件读取第一节点的第一模块中的数据,以及根据节点标识从通用数据类型组件读取与节点标识对应的节点中存储的数据。
根据本发明实施例,判断模块还用于判断某个节点的数据的类型是否与新接收的待存储于所述节点的数据的类型不同,如果不同,则修改节点的第一模块中的数据的类型标识以及值;和/或
判断模块还用于判断是否接收到对自定义数据结构中的某个节点的数据的类型转换操作,如果是,则修改节点的第一模块中的数据的类型标识。
根据本发明实施例,通用数据类型组件还包括传递模块,用于将自定义数据结构在不同或相同程序语言环境的模块间直接传递。
根据本发明实施例,通用数据类型组件可以由C++语言、或脚本语言、VB语言来实现。
根据本发明实施例,当通用数据类型组件由C++语言实现时,该装置还包括C++封装类(C++Wrapper),用于对通用数据类型组件中的自定义数据结构进行封装。
图5为本发明另一实施例的一种存储数据的装置。如图5所示,以利用C++语言来实现本发明的自定义数据结构为例,该装置包括:数据接口IWData,用于接收或发送数据;WData通用数据类型组件,用于根据图1所示的方法存储接收的数据;C++Wrapper封装类,用于对自定义数据结构的通用数据类型WData进行封装,从而可以使用“=”和/或“[]”操作符来实现数据的存储和/或多级存储。而WData通用数据类型组件可以是C++中的Com组件。在本发明实施例中,通过数据接口IWData还可以读取WData中根节点的数据值,并可以根据key读取WData中子节点的数据值。
在图5所示的实施例中,C++Wrapper封装类将WData通用数据类型组件封装成CWData组件。具体地,C++Wrapper封装类利用智能指针CComPtr<IWData>对数据接口IWData进行封装,从而使得在使用CWData组件时和直接通过数据接口IWData来使用WData通用数据类型组件没有区别。同时,CWData通过重载“=”等号操作符,即重新定义“=”的含义,使得“=”具有判断WData中的数据以及数据类型的功能,并通过重载类型转换操作符(比如(int)、(BYTE)等),即对类型转换操作符重新定义,使得类型转换符具有判断WData中的数据以及将WData中的数据进行类型转换的功能,可以实现在C++中在一个通用数据类型的变量中存储不同类型的数据,以及使用任意类型的数据;通过重载“[]”方括号操作符,实现了获取子节点中的WData数据的操作,比如data[“key1”]就等价于获取data中key1对应的子节点中的WData数据。由于返回的子节点中的WData数据仍然是CWData,所以直接多级使用方括号操作符,类似多维数组的使用。
在本发明又一实施例中,以图5所示的装置来说明如何使用存储的数据。具体地,说明对存储的数据的读取、转换以及传递。
1)数据接口IWData的定义以及数据的读取可以如下:
数据接口定义:
interface IWData:IDispatch
{
//读取WData自身Value
HRESULT GetValue(VARIANT*pVar);
HRESULT SetValue(VARIANT var);
//根据key读取子WData的操作,读取的子WData又可以
//有自身的Value和子WData.
HRESULT GetSubData(BSTR bsKey,IWData**ppData);
HRESULT SetSubData(BSTR bsKey,IWData*pData);
......
}
在以上实例中,每个节点中的Value模块可以使用VARIANT结构来实现。
2)将WData用C++Wrapper封装类封装之后得到CWData,利用CWData存储数据,并对存储的数据进行类型转换:
CWData data;
data=10;
data=“string”;
data[1]=10;
data[“key”]=20;
data[“key 1”][“key2”][“key3”]=“test”;
int x=(int)data;
data=(BYTE)3;
由以上的使用实例可以看出,在进行数据类型转换时,可以由用户指定具体的类型。由于CWData通用数据类型中具有数据类型判断功能,可以将data中数据的基本类型直接转换为指定的类型。又或者,可以不需要用户指定具体的类型,而且由CWData通用数据类型根据存储的数据的默认类型对data的基本类型进行转换。比如,当data中的数据是数字时,则转换为数字的默认类型,当data中的数据是字符串时,则转换为字符串的默认类型。
比如,“data=10”中,利用重载的“=”操作符把10存储在data的根节点的Value模块,而之后“data=“string”的操作中,利用重载的“=”操作符把string存储在data的根节点的Value模块中,而此操作同时也是实现了将data根节点的数据类型由整型转换为字符串型,此时类型标识由整型改为字符串型。
当然,也可以不利用C++Wrapper封装类封装WData,而直接使用WData存储数据,并对存储的数据进行使用。但是,这种情况下,操作会比较复杂,比如:
//直接使用WData存储和使用数据
CComPtr<IWData>pData;
CreateWData(&pData);
pData->SetValue(CComVariant(10));
pData->SetValue(CComVariant(“string”));
CComPtr<IWData>pSubData;
pData->GetSubValue(“key”,&pSubData);
pSubData->SetValue(CcomVariant(20));
以上直接使用WData存储和使用数据的结果相当于使用CWData的如下操作的结果:
CWData data;
data=10;
data=“string”;
data[1]=10;
data[“key”]=20;
由此可见,利用C++Wrapper封装类封装WData组件后,对WData的数据的存储和使用更加简洁、方便,从而可以使得通讯系统的运行速度更快,且通讯系统的维护也会更加方便,可以节省通讯系统的维护成本。
3)利用C++Wrapper封装类封装通用数据类型WData,在通讯系统的各模块间传递存储为通用数据类型WData的数据,例如,可以将本发明的技术方案利用在微博系统中以存储微博的用户资料,并在微博系统的各模块间传递存储的微博用户资料。
例如,微博系统中具有A模块如下:
CWData msg;
msg[“id”]=...;
msg[“content”]=“xxxxx”;
msg[“time”]=...;
......
而A模块可以将msg作为参数调用B模块,例如:
ShowMsg(CWData msg);
B模块如下:
Void ShowMsg(CWData msg)
{
//显示内容
...msg[“content”]...
//显示时间
...msg[“time”]...
......
}
从以上A和B模块之间的调用实例可以看出,A模块可以通过一个msg变量将“id”,“content”和“time”三个数据传递给B模块,从而可以实现A和B模块之间的大量数据的传递。因此,可以简化微博系统的建立和维护过程,节省微博系统的开发和维护成本。
以上仅仅是本发明的实施例,但并不意味着本发明的保护范围仅限于所述的实施例。