现在的位置: 首页 > 综合 > 正文

Berkeley DB——Usage

2013年08月27日 ⁄ 综合 ⁄ 共 3516字 ⁄ 字号 评论关闭

 使用

Berkeley DB
供了多种语言的API,但我使用的是其C++
API,虽然C的API来得最直接,但是对我而言比较难用,没有C++的来得舒服——我比较适应面向对象风格的东西。可惜它的C++
API也没有做足够好的封装,使用者还是要写很多繁复的代码,而且要记住它API中会使用到N多的Flag。因此我又把它C++的API包装了一遍,提供
更为直观的API,舍弃那些通常不会用到的Flag参数。
在使用中,我发现了几个令人感到疑惑和郁闷的问题(可能是我水平有限的缘故):
1、.DB文件的文件名仅支持char*的,这在国际化软件环境中会是一个问题。
2、
不支持直接存入string和wstring类型的数据。STL是人们在使用C++过程中普遍会用到的,而若你直接往Berkeley
DB中存入string和wstring(或者Field的类型为string和wstring的结构体)的话,那你将得到不正确的结果——存入数据
后,API返回sucess,但是当你把数据再取出时,只能是最后存入的那对key/data,且data中的内容部分字节发生了乱码,比如你在data
中存入了hello,那可能取出的内容中前面的字符是he,而后面的字符都是乱码。
3、说是支持重复记录(duplicate records),但是当我按照其示例代码调用相应的API时,却发生异常:无效的参数!真不知道Sleepycat哪个环节的工作出了问题。
4、其源码说是可以使用vs2005编译,但是使用vs2005编译会出现大把大把的错误,而使用vc6编译则无问题。

示例

下面是我测试其duplicate records的代码(执行并不成功,报“无效的参数”):

void TestMultiData()
{
    
int ret = 0;
    Db db(NULL,
0);
    ret 
= db.set_flags(DB_DUP);
    ret 
= db.open(NULL,"multi.db",NULL,DB_BTREE,DB_CREATE,0);
    
    ret 
= db.truncate(NULL,0,0);

    Dbt key,data;
    
char *strk,*strd;
    strk 
= "001";
    key.set_data(strk);
    key.set_size(strlen(strk)
+1);
    strd 
= "data1";
    data.set_data(strd);
    data.set_size(strlen(strd)
+1);
    ret 
= db.put(NULL,&key,&data,0);

    strd 
= "data2";
    data.set_data(strd);
    data.set_size(strlen(strd)
+1);
    ret 
= db.put(NULL,&key,&data,0);

    strd 
= "data3";
    data.set_data(strd);
    data.set_size(strlen(strd)
+1);
    ret 
= db.put(NULL,&key,&data,0);


    Dbt dataBuffer;
    dataBuffer.set_data(
&strd);
    dataBuffer.set_ulen(
6*1024);
    dataBuffer.set_flags(DB_DBT_USERMEM);
    
    
try
    
{
        ret 
= db.get(NULL,&key,&dataBuffer,DB_MULTIPLE);
    }

    
catch (DbException &e)
    
{
        cout
<<"  "<<e.what();
    }

    DbMultipleDataIterator iterator(dataBuffer);
    Dbt mdata;
    
while ( iterator.next(mdata) == true )
    
{
        
char *str = (char*)mdata.get_data();
        cout
<<"data:  "<<str<<endl;
    }

}

所有Berkeley DB相关的随笔

posted on 2006-04-12 15:43 风满袖 阅读(1546) 评论(3)  编辑 收藏 网摘 所属分类: Database



评论

#1楼 

2006-05-21 11:22

ipiggg [未注册用户]



下面是IBM的页面(http://www-128.ibm.com/developerworks/cn/linux/l-embdb/?ca=dwcn-newsletter-linux#resources)上的一个例子

和你的例子有2点不同

1:没有初始化DBT类型的key,data

2:下面的程序有这么一段 “/* 把记录写入数据库中,不允许覆盖关键字相同的记录 */

ret = dbp->put(dbp, NULL, &key, &data,DB_NOOVERWRITE); ” ,我不知道你的程序怎么处理的。

#include <db.h>

#include <stdio.h>

#include <stdlib.h>

#include <pthread.h>

/* DB的函数执行完成后,返回0代表成功,否则失败 */

void print_error(int ret)

{

if(ret != 0)

printf("ERROR: %s/n",db_strerror(ret));

}

/* 数据结构DBT在使用前,应首先初始化,否则编译可通过但运行时报参数错误 */

void init_DBT(DBT * key, DBT * data)

{

memset(key, 0, sizeof(DBT));

memset(data, 0, sizeof(DBT));

}

void main(void)

{

DB *dbp;

DBT key, data;

u_int32_t flags;

int ret;

char *fruit = "apple";

int number = 15;

typedef struct customer

{

int c_id;

char name[10];

char address[20];

int age;

} CUSTOMER;

CUSTOMER cust;

int key_cust_c_id = 1;

cust.c_id = 1;

strncpy(cust.name, "javer", 9);

strncpy(cust.address, "chengdu", 19);

cust.age = 32;

/* 首先创建数据库句柄 */

ret = db_create(&dbp, NULL, 0);

print_error(ret);

/* 创建数据库标志 */

flags = DB_CREATE;

/* 创建一个名为single.db的数据库,使用B+树访问算法,本段代码演示对简单数据类型的处理 */

ret = dbp->open(dbp, NULL, "single.db", NULL, DB_BTREE, flags, 0);

print_error(ret);

init_DBT(&key, &data);

/* 分别对关键字和数据赋值和规定长度 */

key.data = fruit;

key.size = strlen(fruit) + 1;

data.data = &number;

data.size = sizeof(int);

/* 把记录写入数据库中,不允许覆盖关键字相同的记录 */

ret = dbp->put(dbp, NULL, &key, &data,DB_NOOVERWRITE);

print_error(ret);

/* 手动把缓存中的数据刷新到硬盘文件中,实际上在关闭数据库时,数据会被自动刷新 */

dbp->sync();

init_DBT(&key, &data);

key.data = fruit;

key.size = strlen(fruit) + 1;

/* 从数据库中查询关键字为apple的记录 */

ret = dbp->get(dbp, NULL, &key, &data, 0);

print_error(ret);

/* 特别要注意数据结构DBT的字段data为void *型,所以在对data赋值和取值时,要做必要的类型转换。 */

printf("The number = %d/n", *(int*)(data.data));

if(dbp != NULL)

dbp->close(dbp, 0);

ret = db_create(&dbp, NULL, 0);

print_error(ret);

}

抱歉!评论已关闭.