明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

PHP中使用DBM作為數(shù)據(jù)庫(kù)(包括排序)

[摘要]在眾多CGI語(yǔ)言中,PHP以其簡(jiǎn)單,快速的優(yōu)點(diǎn)開(kāi)始逐漸成長(zhǎng),使用PHP開(kāi)發(fā)程序的人也越來(lái)越多,而一般PHP用的數(shù)據(jù)庫(kù)就兩種:文本以及MYSQL。文本數(shù)據(jù)庫(kù)讀、寫速度慢,當(dāng)數(shù)據(jù)到達(dá)一定量時(shí)就會(huì)大大的降低速度乃至崩潰!而MYSQL雖然速度快,功能強(qiáng)大,因?yàn)橐话愕拿赓M(fèi)空間都不支持MYSQL,因?yàn)橐话愕拿?..
在眾多CGI語(yǔ)言中,PHP以其簡(jiǎn)單,快速的優(yōu)點(diǎn)開(kāi)始逐漸成長(zhǎng),使用PHP開(kāi)發(fā)程序的人也越來(lái)越多,而一般PHP用的數(shù)據(jù)庫(kù)就兩種:文本以及MYSQL。文本數(shù)據(jù)庫(kù)讀、寫速度慢,當(dāng)數(shù)據(jù)到達(dá)一定量時(shí)就會(huì)大大的降低速度乃至崩潰!而MYSQL雖然速度快,功能強(qiáng)大,因?yàn)橐话愕拿赓M(fèi)空間都不支持MYSQL,因?yàn)橐话愕拿赓M(fèi)空間都不支持MYSQL(有主機(jī)的朋友就不要往下看了)
今天筆者介紹的是DBM數(shù)據(jù)庫(kù),DBM是柏克萊大學(xué)發(fā)展的文件/文本型數(shù)據(jù)庫(kù),在BSD系統(tǒng)中已經(jīng)安裝完畢,即使沒(méi)有安裝,在PHP4.03中也加入了DBM的支持。因此,在大部份支持PHP的空間中都支持DBM(支持PHP的空間詳見(jiàn)www.zphp.com)下面將分步介紹在PHP使用DBM做為數(shù)據(jù)庫(kù):

一、判斷你的空間是否支持DBM的方法:
輸入下面的程序:
----------------------------------------------------
<?
echo dblist();
?>
----------------------------------------------------
保存為dbmtest.php,運(yùn)行,看看是否輸出函數(shù)沒(méi)有定義,如果不是,恭喜……

二、PHP使用DBM的基本函數(shù):
1、int dbmopen(string filepath,string mode);
這個(gè)可以打開(kāi)一個(gè)DBM數(shù)據(jù)庫(kù),其中filepath為DBM數(shù)據(jù)庫(kù)的路徑,mode有4個(gè)參數(shù):"r"以只讀的方式打開(kāi)數(shù)據(jù)庫(kù);"w"以讀寫方式打開(kāi)數(shù)據(jù)庫(kù);"c"以讀寫方式打開(kāi)數(shù)據(jù)庫(kù),若不存在則建立;"n"刪去現(xiàn)有數(shù)據(jù)庫(kù),以讀寫方式打開(kāi)數(shù)據(jù)庫(kù)。
2、boolean dbmclose(int handle); 關(guān)閉一個(gè)已經(jīng)打開(kāi)了的DBM數(shù)據(jù)庫(kù),同時(shí)釋放handle。
3、string dbmfetch(int handle,string key); 取得已經(jīng)打開(kāi)了的handle數(shù)據(jù)庫(kù)的key所對(duì)應(yīng)的值。
4、boolean dbmexists(int handle, string key); 判斷在已經(jīng)打開(kāi)了的handle數(shù)據(jù)庫(kù)中是否存在key。
5、string dbmfirstkey(int handle); 取得已經(jīng)打開(kāi)了的handle數(shù)據(jù)庫(kù)的物理第一個(gè)key。
6、string dbmnextkey(int handle,string key);
取得已經(jīng)打開(kāi)了的handle數(shù)據(jù)庫(kù)中的key所對(duì)應(yīng)的下一個(gè)key(就是dbmnextkey和dbmfirstkey兩個(gè)函數(shù)實(shí)現(xiàn)了dbm的遍歷搜索!)
7、boolean dbminsert(int handle,string key,string value);
在已經(jīng)打開(kāi)了的handle數(shù)據(jù)庫(kù)中插入一個(gè)key,其對(duì)應(yīng)的值為value,如果已經(jīng)存在key則返回false。
8、boolean dbmreplace(int handle, string key, string value);
在已經(jīng)打開(kāi)了的handle數(shù)據(jù)庫(kù)中替換key所對(duì)應(yīng)的值成為value,如果不存在key則返回建立。
9、boolean dbmdelete(int handle,string key);在已經(jīng)打開(kāi)了的handle數(shù)據(jù)庫(kù)中刪除key。


三、使用DBM的注意事項(xiàng):
1、DBM數(shù)據(jù)庫(kù)不像SQL,它只有單純的key/Value的定位,如果你想儲(chǔ)存多種信息,只能將信息用一個(gè)分隔符來(lái)分開(kāi),如下(這里用“ !:! ”做分隔符)
Name !:! TelNo !:! MailAdd //分別儲(chǔ)存了名字、電話及郵箱
讀取時(shí)方法如下:
----------------------------------------------------
$data=explode(' !:! 'dbmfetch($dbmid,$key));
//則$data[o]對(duì)應(yīng)名字,$data[1]對(duì)應(yīng)電話,$data[2]對(duì)應(yīng)郵箱
----------------------------------------------------
2、DBM本身儲(chǔ)存數(shù)據(jù)沒(méi)有任何物理順序,只能通過(guò)自己的處理(見(jiàn)下文)來(lái)排序!
3、DBM不像文本,把一個(gè)db從這個(gè)主機(jī)轉(zhuǎn)移到另一個(gè)主機(jī)上是會(huì)出錯(cuò)的,即一旦建立一個(gè)db文件,就不能轉(zhuǎn)移!
4、DBM在NT下面一個(gè)key對(duì)應(yīng)的值的長(zhǎng)度不能超過(guò)1k個(gè)字符,故在NT下不能使用DBM保留一些有長(zhǎng)度問(wèn)題的東西!
5、關(guān)于DBM中使用中文的KEY:DBM的key不能使用中文,筆者在一共程序中試過(guò),如果使用中文作為key的話當(dāng)key一多(大約20)就會(huì)出現(xiàn)無(wú)法遍歷搜索的問(wèn)題!

四、用DBM做無(wú)序數(shù)據(jù)庫(kù):
用DBM做無(wú)序數(shù)據(jù)庫(kù)(即數(shù)據(jù)無(wú)順序概念)十分簡(jiǎn)單,比文本數(shù)據(jù)庫(kù)要簡(jiǎn)單的多!比如下面是一個(gè)讓用戶輸入用戶名后給出用戶電話的程序:
----------------------------------------------------
<?
if(isset($userid)){
$data=dbmopen("path","r");
if(dbmexists($data,$userid))echo $no=dbmfetch($data,$userid);
else echo "UserID Error!";
dbmclose($data);
}else{
?>
請(qǐng)輸入您的用戶名:
<form action=<?echo$PHP_SELF;?>
<input type="text" name="userid">
<input type="submit" name="submit"></form><?}?>
----------------------------------------------------

五、用DBM做有序數(shù)據(jù)庫(kù):
因?yàn)镈BM沒(méi)有對(duì)數(shù)據(jù)進(jìn)行排序,所以對(duì)于一些按一定順序輸出的程序(如剛才的程序改為顯示所有用戶的電話)則比較棘手,需要人為排序,下面筆者給出兩種方法:
1、排序數(shù)據(jù)法:在這種方法里我們專門用一個(gè)key所對(duì)應(yīng)的值來(lái)記錄順序,那個(gè)key我們?nèi)藶槊麨閟ort,sort對(duì)應(yīng)值如下:
data1's key data2's key data3's key ........ data n's key
其中data n's dey的長(zhǎng)度需要一定(筆者使用的是時(shí)間方法,如下程序可以生成key:)
----------------------------------------------------
function getkey(){
$date=date("ymdHis");
return $date;
}
----------------------------------------------------
這樣用getkey()可以得到一個(gè)類似001203114950的12位key,而每個(gè)key就對(duì)應(yīng)它自己的值(在這里用戶的電話);而用substr($sort,$i*13,12)就可以讀出第i個(gè)用戶的key,下面是顯示列表的代碼:
----------------------------------------------------
<?
//首先要知道有多少個(gè)用戶,可以專門開(kāi)一個(gè)num來(lái)記錄
$data=dbmopen("path","r"); //打開(kāi)數(shù)據(jù)庫(kù)
$sort=dbmfetch($data,"sort"); //讀取sort
for($i=0;$i<$totaluser;$i++){
$key=substr($sort,$i*13,12); //安順序取得key
$telno=dbmfetch($data,$key); //讀出key對(duì)應(yīng)的value
echo $i+1." User's TelNO is ".$telno."<br>";
}
dbmclose($data);
?>
----------------------------------------------------

2、數(shù)組排序法:在這里感謝無(wú)傷兄,是他讓筆者想起用數(shù)組來(lái)排序的。數(shù)組排序的基本原理是將整個(gè)DBM數(shù)據(jù)庫(kù)的每條key讀入數(shù)組,然后根據(jù)每個(gè)key的大小使用usort()等函數(shù)排序然后輸出。
因?yàn)槭菍?duì)key的大小排序,所以key的長(zhǎng)度沒(méi)有什么限制,只要保證后加入的key大于先加入的key就可以實(shí)現(xiàn)先顯示后加入的人,這里用time()來(lái)作為key。
下面是列表代碼:
----------------------------------------------------
$data=dbmopen("path","r"); //打開(kāi)數(shù)據(jù)庫(kù)
$i=1;
for($key=dbmfirstkey($data);$key;$key=dbmnextkey($data,$key)){
$sort[$i]=$key;
$i++;
} //遍歷取得所有的key
usort($sort); //安大小排序
for($i=0;$i<count($sort);$i++)
echo $i+1." User's TelNO is ".dbmfetch($data,$sort[$i])."<br>";
dbmclose($data);
----------------------------------------------------
以上兩種方法在運(yùn)行時(shí)占用內(nèi)存(用于排序)第一種比第二種要大一點(diǎn),不過(guò)對(duì)于運(yùn)算量來(lái)講,第一種方法則要小于第二種,至于想用哪種方法就隨你意了(如果你興趣,可以試試兩者的CPU占用率)。
筆者在經(jīng)過(guò)了N次(N>50)實(shí)驗(yàn)后完成了這篇文章僅以此獻(xiàn)給窮苦的仍在用txt的朋友們相信也不是所有看CN的人都有自己的主機(jī)!如果有什么不明白的,來(lái)這里看看:www.zphp.com。
筆者不是什么高手,不過(guò)因?yàn)閹缀跽也坏皆赑HP上使用DBM數(shù)據(jù)庫(kù)的資料(包括英文資料,不過(guò)Perl方面的卻不少)。最好留一個(gè)筆者用DBM寫的論壇,大家可以試試速度:www.zphp.com/demo/dbmbbs/ !