Berkeley DB使用全解

时间:2021-06-12 12:08:29
 
在开发桌面级应用程序时,常常需要用到可持续存储技术,做为保存程序在退出之前所使用的数据,如变量,对象,窗口位置,大小.一般我们会使用office access这类桌面型文件数据库,或者是使用注册表.但是它们都有一些不尽人意的缺陷.比如:
1.       mdb文件无法在没有安装office的系统*问,直少得需要为它单独安装一个组件
2.       它与注册表没法实现c++结构存储,(但是可以使用复合文档的技术来实现,以后再讲)
 
由于以上等原因,所以我们需要选择一款,适合桌面级的文件数据库.
 
版本:
Berkeley DB 4.6.18
注意,它有C和C++两个版本,都是跨本台的,这里我们主要介绍C++的
建立数据库:
#define DATABASE “MyDatabase.db” //数据库文件
Db db(NULL,0);
if (ret = db.open(NULL,DATABASE,NULL,DB_BTREE,DB_CREATE,0))
{
     db.err( ret, "%s", DATABASE);
     exit (1);
}
db.close(0);// 关闭数据库
 
插入一条记录:
注意,到目前为止,我发现它只能做到一个关键字对应一个值.
这里使用一个C++结构做为例子,稍复杂点
 
// 这里建立KEY
// 它可以是任何一类型数据,BerkeleyDB是以内存内容比较的,所以它也可以是个结构,当然你//不怕麻烦
Dbt key
     key.set_data((void *)&index);
     key.set_size(4);
    
也可以
     Dbt key( mykey ,6); // 多留个/0
 
// 建立一个结构体并赋值,里面就是我们要存放的value
typedef struct
{
     int _id;
     char _username[30];
     char _password[30];
}Foo,*PFoo;
Dbt data;
    // 保证每个字段都准确的写入这个缓冲,因为你写进去什么样,读出来就是什么样
     Foo foo = {1,"arthur","sj123"};
     size_t len = 4+4+strlen(foo._username)+4+strlen(foo._password);
     char *buf = new char[len];
     memset(buf,0,len);
     int slen = 0;
     memcpy(buf,(char*)&foo._id,sizeof(int));
     slen += sizeof(int);
     int namelen = strlen(foo._username);
     int passlen = strlen(foo._password);
     memcpy(buf+slen,(void*)&namelen,sizeof(int));
     slen += sizeof(int);
     memcpy(buf+slen,foo._username,namelen);
     slen += namelen;
     memcpy(buf+slen,(void*)&passlen,sizeof(int));
     slen += sizeof(int);
     memcpy(buf+slen,foo._password,passlen);
     slen += passlen;
 
     data.set_data((void *)buf); // 写入Dbt
     data.set_size(slen);         // 设置大小,很关键,别算错了
 
     // 写入数据库
    if ((ret = db.put( NULL, &key, &data, 0)) == 0)  
              printf("db: %s: key stored./n", (char *)key.get_data());
         else
              db.err( ret, "DB->put");   // 出错,打印相当错误信息
 
从数据库里读出记录:
1.      查找一个key,取出它的value
 
     Dbt key( mykey ,6); // 多留个/0
     Dbt data;     // 存储将要读出来的数据
    if((ret = db.get(NULL,&skey,&data,0)) == 0)
         printf("db: %s: key retrieved: data was %s:%x./n",
(char *)key.get_data(),data.get_data());
     else
         db.err( ret, "DB->get");
      
2.       遍历所有的key与value
Dbt key,data; //声时要存储数据变量
Dbc cursor;   // 游标
Db.cursor (NULL,&cursor,0);     // 取得当前数据库的游标
while((ret = cursor->get(&key,&data,DB_NEXT))==0)   //DB_NEXT 也就是指向下一条
     {
         printf("db: %s: key retrieved: data was %s./n",(char *)key.get_data());
}
 //data 则需要还原为你的结构,与上面的方法相反,这里不多做介绍了.
 
删除记录:
Dbt key( mykey ,6);
if((ret = db.del(NULL,&key,0))==0)
          printf("delete %s/n",(char*)key.get_data());
     else
         db.err(ret,"DB->delete");
删除所有记录:
Dbt key,data; //声时要存储数据变量
Dbc cursor;   // 游标
Db.cursor (NULL,&cursor,0);     // 取得当前数据库的游标
while((ret = cursor->get(&key,&data,DB_NEXT))==0)   //DB_NEXT 也就是指向下一条
     {
         printf("db: %s: key retrieved: data was %s./n",(char *)key.get_data());
         cursor->del(0);
}
       //不知道为什么,当我删除所有记录的之后,文件里仍然可以看到我先前写入的数据.但是程序是无法读出了.