分享
 
 
 

DBM、GDBM与C语言跨平台代码研究

王朝c/c++·作者佚名  2006-01-31
窄屏简体版  字體: |||超大  

DBM与GDBM与跨平台代码研究

关键字:

DBM: UNIX系统的数据库,使用hash保存非结构化数据。它不支持SQL。

GDBM:DBM的GNU版本。

跨平台C语言代码:具有跨平台特性的C语言代码。

1. 简介

符合X/Open技术规范的UNIX版本自备了一个数据库。但这个数据库不符合ANSI标准的SQL技术规范(不支持SQL语句)。它只是一个存储检索数据的例程。

dbm、gdbm适合存储静态的,索引化的数据结构。它在创建数据项时非常慢,但检索数据项时非常快。

本文给出了dbm、gdbm各自的函数简要说明,最后给出了能够兼容DBM、GDBM两个不同数据库的C代码编写建议。

2. dbm

dbm使用两个数据文件,扩展名为”.pag”和”.dir”。但对数据库的操作返回值只有一个。注意:不要使用读写函数直接操作数据文件,应该使用dbm提供的数据操作函数访问数据。

2.1.

数据结构

数据、索引都使用以下结构保存:

typedef

struct {

char *dptr;

int dsize;

} datum;

数据库的访问结构(等同于FILE):

typedef

struct {int dummy[10];} DBM;

2.2.

函数简介

#include <ndbm.h>

/*打开数据库*/

DBM *dbm_open(const char *filename, /*数据库文件名(两个文件,后缀不同)*/

int

file_open_flags, /*与open函数相同,文件打开标志*/

mode_t

file_mode /*与open函数相同,文件打开模式*/

);

成功时返回DMB类型指针,失败返回NULL

/*存储数据*/

int dbm_store(DBM *database_descriptor, /*前面打开数据库操作返回的结构*/

datum

key, /*检索数据的关键字*/

datum

content, /*用于保存数据的结构*/

int

store_mode /*如果为dbm_insert,则数据存在时操作会失败, 如果dbm_replace,则覆盖已经存在的数据*/

);

如果数据库打开方式为“dbm_insert”,而保存时该key对应的数据已经存在,则返回1;

如果出现其他错误,返回一个负数;

操作成功,返回0;

/*检索数据*/

datum dbm_fetch(DBM *database_descreiptor, /*dbm_open返回的数据结构*/

datum

key /*检索使用的关键字*/

);

如果找到,则返回结构dptr和dsize分别赋值为数据指针和数据大小,如果没找到,则dptr赋值为NULL。

返回的datum结构中包含指向记录数据的指针,数据记录仍然在dbm内部某个存储区,如果需要,应把它拷贝到其他变量中。

/*关闭数据库*/

void dbm_close(DBM *database_descriptor); /*dbm_open返回的数据结构*/

/*其他函数简介*/

int dbm_delete(DBM

*database_descriptor,datum key); /*删除索引为key的数据*/

操作成功返回0;

int dbm_error(DBM *database_descriptor); /*对数据库进行简单测试。没有错误返回0。*/

没有错误返回0;

dbm_firstkey(),dbm_nextkey()一般成对使用,用于检索数据库中全部数据。

例如:

for(key=dbm_firstkey(db_ptr);key.dptr;key=dbm_nextkey(db_prt));

3. gdbm

gdbm使用一个数据文件,与dbm不同。注意:不要使用读写函数直接操作数据文件,应该使用gdbm提供的数据操作函数访问数据。

3.1.

数据结构

数据、索引都使用以下结构保存(与dbm相同):

typedef

struct {

char *dptr;

int dsize;

} datum;

数据库的访问结构(等同于FILE):

typedef

struct {int dummy[10];} *GDBM_FILE;

3.2.

函数简介

#include <gdbm.h>

/*打开数据库*/

GDBM_FILE *gdbm_open(

char

*name; /*用于保存数据库路径文件名*/

int block_size; /*设置内存与磁盘直接io传递数据的单位,最小512字节*/

int

read_write; /*可设置为:GDBM_READER、GDBM_WRITER、

GDBM_WRCREATER、GDBM_NEWDB*/

int mode; /*文件打开模式。与chmod(2)、open(2)相似*/

):

成功返回GDBM_FILE类型指针,否则返回NULL。

/*存储数据*/

int gdbm_store(GDBM_FILE *database_descriptor, /*前面打开数据库操作返回的结构*/

datum

key, /*检索数据的关键字*/

datum

content, /*用于保存数据的结构*/

int

store_mode /*如果为gdbm_insert,则数据存在时操作会失败, 如果gdbm_replace,则覆盖已经存在的数据*/

); /*与DBM相同*/

如果一个只读打开的数据库调用了这个函数,则返回-1;

如果数据库以GDBM_INSTERT方式打开,且保存的数据关键字已经存在,那么返回1;

其他情况返回0(操作成功);

注意:gdbm的存储数据大小没有限制,这与dbm、ndbm不同。

/*检索数据*/

datum gdbm_fetch(GDBM_FILE *database_descreiptor, /*gdbm_open返回的数据结构*/

datum

key /*检索使用的关键字*/

); /*与DBM相同*/

如果返回值的dptr字段为NULL,则没有找到数据;

注意:gdbm自动分配dptr的存储空间(使用malloc(3C)),但不会自动释放这个空间。释放空间的责任交给了程序员完成。

/*关闭数据库*/

void gdbm_close(GDBM_FILE *database_descriptor);

/*gdbm_open返回的数据结构*/

/*其他函数简介*/

int gdbm_exist(GDBM_FILE dbf,datum key); /*检查数据库中是否存在key对应的数据*/

返回true表示找到数据,返回false表示数据不存在。

int gdbm_delete(GDBM_FILE *database_descriptor,datum

key); /*删除索引为key的数据*/

返回0表示操作成功,返回-1表示没有找到key对应的数据。

char *gdbm_strerror(gdbm_error errno); /*把错误代号转换为英文字符串。*/

返回可打印的错误描述字符串。

int gdbm_setopt(GDBM_FILE dbf, int option,

int value, int size); /*设置已经打开的数据库的参数,可以设置系统内部cache大小、设置快速模式(此功能已过时)、打开或关闭中央空闲数据块存储池。*/

返回0表示设置操作成功,返回-1表示操作失败。

int gdbm_fdesc(dbf); /*多用户共享时,为了给数据库文件加锁,设置已打开的数据库的标志。*/

key=gdbm_firstkey(dbf)

nextkey=gdbm_nextkey(dbf,key); /*与dbm相似,用于访问所有数据。*/

例如:

key

gdbm_firstkey(dbf);

while(key.dptr)

{

nextkey

= gdbm_nextkey(dbf,key);

… /*某些循环中的处理操作*/

key

= nextkey;

}

4. 研究:代码如何同时兼容dbm、gdbm

针对不同系统,有的使用dbm(ndbm),有的使用gdbm。为了使数据库访问的C代码具有更好的跨平台能力,我们需要对代码进行部分修改,同时,需要针对不同平台写不同的配置文件。这样,我们的数据库操作代码就拥有了更强的平台适应性。

具体方法如下:

1.

首先,我们编写一个平台相关的Makefile文件。

例如,Red Hat Linux 6.1使用了dbm库,而Red Hat

Linux 9.0使用的使gdbm库,这时,Red Hat Linux 6.1的编译文件命名为my_dbm.make,Red Hat Linux 9.0的编译、安装文件命名为my_gdbm.make。

平台1:支持DBM的Makefile文件,在My_dbm.make我们需要写如下代码:

DBMLIB = -ldbm

平台2:支持gdbm的Makefile文件,在RH_linux_9.0.make我们需要写如下代码:

DBMLIB = -lgdbm

2.

然后,编写不同头文件。

例如,我们需要编写两个配置文件,分别命名为my_dbm.h、my_gdbm.h,把不同的定义包含在其中。

平台1:支持DBM的配置文件,在My_dbm.h我们需要写如下代码:

#define NDBM

#include <ndbm.h>

平台2:支持gdbm的配置文件,在my_gdbm.h我们需要写如下代码:

#define GDBM

#include <gdbm.h>

3.

让用户选择,把不同的配置文件拷贝到一个相同名字的配置文件,给出一个与平台无关的编译、安装脚本。

例如,用户查找系统配置资料,得知当前系统只支持DBM,那么用户需要把my_dbm.make拷贝为代码跟目录的Makefile,把my_dbm.h拷贝为config.h文件。

4.

修改数据库操作代码,使两套(或更多)数据库操作函数同时存在。

例如:修改代码,把头文件定义从原来的

#include <dbm.h> /*或者 #include <gdbm.h> */

修改为

#include “config.h”

对所有与数据库操作相关的函数加入条件编译语句。

#ifdef DBM

DBM *mydb; /*DBM,GDBM数据库操作指针类型不同!*/

dbm_fetch( … ); /*其他函数类似,注意某些函数参数个数不同!*/

#endif

#ifdef

GDBM

GDBM_FILE

*mydb; /*为了操作一致,我们选择相同的变量名字。*/

gdbm_fetch(

… ); /*其他函数类似*/

#endif

现在,可以说马上就要大功告成了。但是,别忘了给出说明文档README,告诉用户如何才能使用你代码中的平台适应能力(现在只有你自己知道这个特性)。这个README文档中必须包含:

1.

如何确定自己平台的使用的数据库

—— 可以使用man gdbm,man dbm;

2.

与平台相关的编译、安装文件拷贝到哪个目录的Makefile文件;

3.

与平台相关的头文件拷贝到哪个目录的config.h文件;

4.

如何编译、安装、使用你的代码;

前面是对C代码跨平台编程的一点尝试。大多数平台相关特性都可以使用前面提到的方法完成。这里也可以看出,C语言代码必须完成多套函数,在编译期根据平台特性,选择适合自己平台的部分编译、安装。它与JAVA代码的跨平台概念完全不同。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有