在开发桌面级应用程序时,常常需要用到可持续存储技术,做为保存程序在退出之前所使用的数据,如变量,对象,窗口位置,大小.一般我们会使用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);
}
//不知道为什么,当我删除所有记录的之后,文件里仍然可以看到我先前写入的数据.但是程序是无法读出了.