Berkeley DB——Store Structure 如何存储结构体

Introduction

Berkeley DB适合存储简单的数据,比如那些c/c++定义的类型,诸如intfloatcharwchar_t等等。因为DB虽然可以存入任意类型的数据,但是它只会原原本本按照字节将数据存入(entirely 8-bit clean data),其它的工作需要我们自己负责。

如果我们定义了一个只包含简单数据类型属性的结构体,且我们给这个结构体对象赋值的时候,每个属性都不是动态分配内存的,那我们直接使用Db::put方法可以将其存入数据库中,且简单的Db::get后强制转换就能将其还原出来——可是这在实际开发中几乎是不可能的。所以在将structure object存入DB的时候我们需要做更多的工作——我们需要将这个对象转换为字节数组unsigned chararray,然后再存入DB中;get数据的时候需要将这个array再还原为我们的structure object,有术语来指明它们:marshallingun-marshalling。除此之外,还有一个办法,就是使用二进制的序列化和反序列化。

 

Marshalling and Un-marshalling

这是一种比较麻烦的办法,也是一种非常不灵活,不美观的方式,但是它是有效的。

使用run-length的方式——先将属性的长度存入array中,然后再将此属性使用内存拷贝的方式存入array;还原的时候先取得长度,然后根据此长度得到此属性的值。例子:

struct MyStruct

{

       wchar_t* Name;

       wchar_t* Description;

      

       unsigned int GetSize()

       {

              unsigned int size = 0;

              size += sizeof(size);

              size += wcslen(Name)*2+2;

              size += sizeof(size);

              size += wcslen(Description)*2+2;

              return size;

       }

       //Marshall the struct to a run-length byte array

       unsigned int Marshall (unsigned char* buffer)

       {

              size_t bytesCount=GetSize();

              size_t len = 0;

              unsigned char *p;

              memset(buffer,0,bytesCount);

              p = &buffer[0];

              //Name

              len = wcslen(Name)*2+2;

              memcpy(p,&len,sizeof(len));//id length

              p+=sizeof(len);

              memcpy(p,Name,len);

              p+=len;

              //description

              len = wcslen(Description)*2+2;

              memcpy(p,&len,sizeof(len));//id length

              p+=sizeof(len);

              memcpy(p,Description,len);

              p+=len;

              return bytesCount;

       }

       //Unmarshall the byte array to struct

       void Unmarshall(unsigned char* buffer)

       {

              unsigned char* p;

              size_t len = 0;

              p = &buffer[0];

              //Name

              memcpy(&len,p,sizeof(len));

              p+= sizeof(len);

              Name = (wchar_t*)malloc(len);

              memcpy(Name,p,len);

              p+= len;

              //Description

              memcpy(&len,p,sizeof(len));

              p+= sizeof(len);

              Description = (wchar_t*)malloc(len);

              memcpy(Description,p,len);

              p+= len;

       }

};

使用Marshall来得到byte array,将此byte array存入DB。而从DBgetbyte array后,只需要使用Unmarshall方法就可以还原该structure object了。缺点显而易见:如果的struct变动了,多处代码都需要变动,代码比较繁复冗长,特别是当struct的属性比较多的时候。

Serialization and Un-serialization

序列化和反序列化已经是普遍使用的技术了,我们可以使用该技术将对象转换为byte array(或者text),和将byte array(或者text)还原为对象。序列化和反序列化的方法有很多,根据实际情况选择合适的方法。

 

你可能感兴趣的:(Berkeley DB——Store Structure 如何存储结构体)