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; }

|