Berkeley DB使用方法

类别:编程语言 点击:0 评论:0 推荐:

Berkeley DB是Sleepcat开发的开源的嵌入式数据库。具有轻巧、可扩展的优点。
但是它不支持SQL语句,而且操作起来相对比较复杂。
下面讲讲在VC下为了使其能够存储数据结构做的封装。
在google搜索Berkely DB 进入sleepycat下载zip安装包,编译。
建立工程TestBerkeleyDB,拷贝libdb43.dll和libdb43.lib到当前工程下,添加libdb43.dll到工程的setting。
把db.h和db_cxx.h拷贝到当前目录下。
添加icqtypes.h:
#ifndef _ICQ_TYPES_H_
#define _ICQ_TYPES_H_

#include <string>
#include <list>
#include <vector>
#include <bitset>

using namespace std;

typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long uint32;

typedef list<string>  StrList;
typedef list<void *> PtrList;
typedef list<uint32> UinList;

#endif

添加icqdb.h;
#ifndef _ICQ_DB_H
#define _ICQ_DB_H

#include "icqtypes.h"
#include "db_cxx.h"


#define MAX_BLOCK_SIZE 4096

class DBOutStream {
public:
 DBOutStream() {
  cursor = data;
 }
 char *getData() {
  return data;
 }
 int getSize() {
  return (cursor - data);
 }

 DBOutStream &operator <<(uint8 b);
 DBOutStream &operator <<(uint16 w);
 DBOutStream &operator <<(uint32 dw);
 DBOutStream &operator <<(const char *str);
 DBOutStream &operator <<(const string &str) {
  return operator <<(str.c_str());
 }
 DBOutStream &operator <<(StrList &strList);
 
private:
 char data[MAX_BLOCK_SIZE];
 char *cursor;
};

class DBInStream {
public:
 DBInStream(void *d, int n) {
  cursor = data = (char *) d;
  datalen = n;
 }
 DBInStream &operator >>(uint8 &b);
 DBInStream &operator >>(uint16 &w);
 DBInStream &operator >>(uint32 &dw);
 DBInStream &operator >>(string &str);
 DBInStream &operator >>(StrList &strList);

private:
 char *data;
 char *cursor;
 int datalen;
};

class DBSerialize {
public:
 virtual void save(DBOutStream &out) = 0;
 virtual void load(DBInStream &in) = 0;
};


#endif
添加icqdb.cpp:
#include "stdafx.h"
#include "icqdb.h"
#include "string.h"
#include "icqtypes.h"


#define INDEX_USER  0
#define INDEX_OPTIONS 0xffffffff
#define INDEX_GROUP  0xfffffffe

DBOutStream &DBOutStream::operator <<(uint8 b)
{
 if (cursor <= data + MAX_BLOCK_SIZE - sizeof(b))
  *cursor++ = b;
 return (*this);
}

DBOutStream &DBOutStream::operator <<(uint16 w)
{
 if (cursor <= data + MAX_BLOCK_SIZE - sizeof(w)) {
  *(uint16 *) cursor = w;
  cursor += sizeof(w);
 }
 return (*this);
}

DBOutStream &DBOutStream::operator <<(uint32 dw)
{
 if (cursor <= data + MAX_BLOCK_SIZE - sizeof(dw)) {
  *(uint32 *) cursor = dw;
  cursor += sizeof(dw);
 }
 return (*this);
}

DBOutStream &DBOutStream::operator <<(const char *str)
{
 uint16 len = strlen(str) + 1;
 if (cursor <= data + MAX_BLOCK_SIZE - sizeof(len) - len) {
  *this << len;
  memcpy(cursor, str, len);
  cursor += len;
 }
 return (*this);
}

DBOutStream &DBOutStream::operator <<(StrList &strList)
{
 uint16 n = 0;
 char *old = cursor;
 cursor += sizeof(n);
 
 StrList::iterator i;
 for (i = strList.begin(); i != strList.end(); i++) {
  operator <<(*i);
  n++;
 }
 char *p = cursor;
 cursor = old;
 operator <<(n);
 cursor = p;
 return (*this);
}

DBInStream &DBInStream::operator >>(uint8 &b)
{
 if (cursor <= data + datalen - sizeof(b))
  b = *cursor++;
 else
  b = 0;
 return (*this);
}

DBInStream &DBInStream::operator >>(uint16 &w)
{
 if (cursor <= data + datalen - sizeof(w)) {
  w = *(uint16 *) cursor;
  cursor += sizeof(w);
 } else
  w = 0;
 return (*this);
}

DBInStream &DBInStream::operator >>(uint32 &dw)
{
 if (cursor <= data + datalen - sizeof(dw)) {
  dw = *(uint32 *) cursor;
  cursor += sizeof(dw);
 } else
  dw = 0;
 return (*this);
}

DBInStream &DBInStream::operator >>(string &str)
{
 uint16 len;
 operator >>(len);

 if (cursor <= data + datalen - len && !cursor[len - 1]) {
  str = cursor;
  cursor += len;
 } else
  str = "";
 return (*this);
}

DBInStream &DBInStream::operator >>(StrList &strList)
{
 uint16 num;
 operator >>(num);
 int n = (int) num;

 strList.clear();
 while (n-- > 0) {
  string s;
  operator >>(s);
  strList.push_back(s);
 }
 return (*this);
}

添加CPerson类:
CPerson.h:
// Person.h: interface for the CPerson class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_PERSON_H__D259A8B7_7ACB_4624_8C9E_394B11FFA5C9__INCLUDED_)
#define AFX_PERSON_H__D259A8B7_7ACB_4624_8C9E_394B11FFA5C9__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "icqdb.h"

class CPerson: public DBSerialize
{
public:
 CPerson();
 virtual ~CPerson();
public:
 string Name;
 uint16 age;
 string Describe;
 void save(DBOutStream &out);
 void load(DBInStream &in);
};
#endif // !defined(AFX_PERSON_H__D259A8B7_7ACB_4624_8C9E_394B11FFA5C9__INCLUDED_)

Person.cpp:
// Person.cpp: implementation of the CPerson class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "TestBerkeleyDB.h"
#include "Person.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CPerson::CPerson()
{

}

CPerson::~CPerson()
{

}
void CPerson::save(DBOutStream &out)
{
 out << Name << age << Describe;
}

void CPerson::load(DBInStream &in)
{
 in >> Name >> age >> Describe;
}

下面是主函数:
// TestBerkeleyDB.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "TestBerkeleyDB.h"
#include "db_cxx.h"
#include "icqtypes.h"
#include "icqdb.h"
#include "Person.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// The one and only application object

CWinApp theApp;

//using namespace std;

bool delPeople(char *fileName, string index)
{
 Db db(NULL, 0); // Instantiate the Db object
 u_int32_t oFlags = DB_CREATE; // Open flags;
 try {
 // Open the database
 db.open(NULL, // Transaction pointer
   fileName, // Database file name
   NULL, // Optional logical database name
   DB_BTREE, // Database access method
   oFlags, // Open flags
   0); // File mode (using defaults)
   // DbException is not subclassed from std::exception, so
   // need to catch both of these.
  } catch(DbException &e) {
  // Error handling code goes here
  } catch(std::exception &e) {
  // Error handling code goes here
  }
 Dbc *cursorp;
 try {
  // Database open omitted
  // Get the cursor
  db.cursor(NULL, &cursorp, 0);
  // Set up our DBTs
  Dbt data;
  Dbt key;
  key.set_data((void*)index.c_str());
  key.set_size(index.length()+1);
  
  // Iterate over the database, deleting each record in turn.
  int ret;
  while ((ret = cursorp->get(&key, &data,
   DB_SET)) == 0) {
   cursorp->del(0);
  }
 } catch(DbException &e) {
  db.err(e.get_errno(), "Error!");
 } catch(std::exception &e) {
  db.errx("Error! %s", e.what());
 }
  // Cursors must be closed
 if (cursorp != NULL)
   cursorp->close();
 db.close(0);
 return true;
}

bool delPeople(char *fileName, uint32 index)
{
 Db db(NULL, 0); // Instantiate the Db object
 u_int32_t oFlags = DB_CREATE; // Open flags;
 try {
  // Open the database
  db.open(NULL, // Transaction pointer
   fileName, // Database file name
   NULL, // Optional logical database name
   DB_BTREE, // Database access method
   oFlags, // Open flags
   0); // File mode (using defaults)
  // DbException is not subclassed from std::exception, so
  // need to catch both of these.
 } catch(DbException &e) {
  // Error handling code goes here
 } catch(std::exception &e) {
  // Error handling code goes here
 }
 Dbc *cursorp;
 try {
  // Database open omitted
  // Get the cursor
  db.cursor(NULL, &cursorp, 0);
  // Set up our DBTs
  Dbt data;
  Dbt key;
  key.set_data(&index);
  key.set_size(sizeof(index));
  
  // Iterate over the database, deleting each record in turn.
  int ret;
  while ((ret = cursorp->get(&key, &data,
   DB_SET)) == 0) {
   cursorp->del(0);
  }
 } catch(DbException &e) {
  db.err(e.get_errno(), "Error!");
 } catch(std::exception &e) {
  db.errx("Error! %s", e.what());
 }
 // Cursors must be closed
 if (cursorp != NULL)
  cursorp->close();
 db.close(0);
 return true;
}

bool loadPeople(char *fileName, uint32 index, DBSerialize &obj)
{
 Db db(NULL, 0); // Instantiate the Db object
 u_int32_t oFlags = DB_CREATE; // Open flags;
 try {
 // Open the database
 db.open(NULL, // Transaction pointer
    fileName, // Database file name
    NULL, // Optional logical database name
    DB_BTREE, // Database access method
    oFlags, // Open flags
    0); // File mode (using defaults)
    // DbException is not subclassed from std::exception, so
    // need to catch both of these.
    } catch(DbException &e) {
    // Error handling code goes here
    } catch(std::exception &e) {
    // Error handling code goes here
    }

 Dbt key, data;
 key.set_data(&index);
 key.set_size(sizeof(index));

 if (db.get(NULL, &key, &data, 0) != 0) {
  db.close(0);
  return false;
 }

 DBInStream in(data.get_data(), data.get_size());
 obj.load(in);

 db.close(0);
 return true;
}

bool loadPeople(char *fileName, string index, DBSerialize &obj)
{
 Db db(NULL, 0); // Instantiate the Db object
 u_int32_t oFlags = DB_CREATE; // Open flags;
 try {
 // Open the database
 db.open(NULL, // Transaction pointer
    fileName, // Database file name
    NULL, // Optional logical database name
    DB_BTREE, // Database access method
    oFlags, // Open flags
    0); // File mode (using defaults)
    // DbException is not subclassed from std::exception, so
    // need to catch both of these.
    } catch(DbException &e) {
    // Error handling code goes here
    } catch(std::exception &e) {
    // Error handling code goes here
    }

 Dbt key, data;
 key.set_data((void*)index.c_str());
 key.set_size(index.length()+1);

 if (db.get(NULL, &key, &data, 0) != 0) {
  db.close(0);
  return false;
 }

 DBInStream in(data.get_data(), data.get_size());
 obj.load(in);

 db.close(0);
 return true;
}

bool savePeople(char *fileName, uint32 index, DBSerialize &obj)
{
 Db db(NULL, 0); // Instantiate the Db object
 u_int32_t oFlags = DB_CREATE; // Open flags;
 try {
 // Open the database
 db.open(NULL, // Transaction pointer
    fileName, // Database file name
    NULL, // Optional logical database name
    DB_BTREE, // Database access method
    oFlags, // Open flags
    0); // File mode (using defaults)
    // DbException is not subclassed from std::exception, so
    // need to catch both of these.
    } catch(DbException &e) {
    // Error handling code goes here
    } catch(std::exception &e) {
    // Error handling code goes here
    }
    
 DBOutStream out;
 obj.save(out);

 Dbt key, data;
 key.set_data(&index);
 key.set_size(sizeof(index));
 data.set_data(out.getData());
 data.set_size(out.getSize());
 int ret = db.put(NULL, &key, &data, 0) ;
 db.close(0);
 return (ret == 0);
}

bool savePeople(char *fileName, string index, DBSerialize &obj)
{
 Db db(NULL, 0); // Instantiate the Db object
 u_int32_t oFlags = DB_CREATE; // Open flags;
 try {
 // Open the database
 db.open(NULL, // Transaction pointer
    fileName, // Database file name
    NULL, // Optional logical database name
    DB_BTREE, // Database access method
    oFlags, // Open flags
    0); // File mode (using defaults)
    // DbException is not subclassed from std::exception, so
    // need to catch both of these.
    } catch(DbException &e) {
    // Error handling code goes here
    } catch(std::exception &e) {
    // Error handling code goes here
    }   
 DBOutStream out;
 obj.save(out);

 Dbt key, data;
 key.set_data((void*)index.c_str());
 key.set_size(index.length()+1);
 data.set_data(out.getData());
 data.set_size(out.getSize());
 int ret = db.put(NULL, &key, &data, 0);
 db.close(0);
 return (ret == 0);
}

bool printAllPeople(char *fileName)
{
 Db db(NULL, 0); // Instantiate the Db object
 u_int32_t oFlags = DB_CREATE; // Open flags;
 try {
  // Open the database
  db.open(NULL, // Transaction pointer
   fileName, // Database file name
   NULL, // Optional logical database name
   DB_BTREE, // Database access method
   oFlags, // Open flags
   0); // File mode (using defaults)
  // DbException is not subclassed from std::exception, so
  // need to catch both of these.
 } catch(DbException &e) {
  // Error handling code goes here
 } catch(std::exception &e) {
  // Error handling code goes here
 }
 Dbc *cursorp;
 try {
  // Database open omitted
  // Get the cursor
  db.cursor(NULL, &cursorp, 0);
  // Set up our DBTs
  Dbt data;
  Dbt key;
  // Iterate over the database, deleting each record in turn.
  int ret;
  while ((ret = cursorp->get(&key, &data,
   DB_NEXT)) == 0) {
   //cursorp->del(0);
   CPerson p;
   DBInStream in(data.get_data(), data.get_size());
   p.load(in);
   printf("%s\n",p.Describe);

  }
 } catch(DbException &e) {
  db.err(e.get_errno(), "Error!");
 } catch(std::exception &e) {
  db.errx("Error! %s", e.what());
 }
 // Cursors must be closed
 if (cursorp != NULL)
  cursorp->close();
 db.close(0);
 return true;
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
 int nRetCode = 0;

 // initialize MFC and print and error on failure
 if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
 {
  // TODO: change error code to suit your needs
  cerr << _T("Fatal Error: MFC initialization failed") << endl;
  nRetCode = 1;
 }
 else
 {
  string index1 = "Liang Zhijian";
  string index2 = "Zou Dan";
  CPerson p1;
  p1.age = 0;
  p1.Name = "Liang Zhijian";
  p1.Describe = "student1";

  savePeople("mydb.db",index1,p1);

  CPerson p2;
  p2.age = 1;
  p2.Name = "Zou Dan";
  p2.Describe = "student2"; 
  savePeople("mydb.db",index2,p2);

  CPerson p3;
  loadPeople("mydb.db","Liang Zhijian",p3);
  printf("%s\n",p3.Describe);
  
  printAllPeople("mydb.db");
  delPeople("mydb.db","Liang Zhijian");
  printAllPeople("mydb.db");
 }
 
 return nRetCode;
}


 

本文地址:http://com.8s8s.com/it/it24452.htm