作者的1.0版: /* 本代码开源,您可以对其进行修改. 下面文字请不要修改. ********************************************* php文本数据库类1.0版 powerd by bpns mysite:http://space.tju.cn/site/redboy/ 2006-4-20 ********************************************* 为了您的数据库安全,请在此程序中更改您的数据默认目录 将function TxtDB($name,$mod='w',$path='my_dbm') 中$path='my_dbm'修改成你自己设定的目录,如$path='abc123_dbm', 并将根目录下的my_dbm文件夹对行对应的更名. */ class TxtDB { var $name='';//文本数据库名 var $path=''; var $minLen=20; var $isError; var $dbh; var $indxh; var $lfth; var $lckh; var $rcdCnt=0; var $maxID=0; var $leftCnt=0; var $DBend=0; var $mod='w'; function TxtDB($name,$mod='w',$path='bpns_dbm')//修改数据库的默认文件夹在此修改 { $this->name=$name; $this->path=$path.'/'.$name; $this->isError=0; $this->mod=$mod; $path=$this->path; if ($name!='') { @mkdir($this->path,0777); if (!file_exists($path.'/'.$name.'.tdb')) $this->dbh=fopen($this->path.'/'.$name.'.tdb','w+'); else $this->dbh=fopen($path.'/'.$name.'.tdb','r+'); if (!file_exists($path.'/'.$name.'.indx')) $this->indxh=fopen($this->path.'/'.$name.'.indx','w+'); else $this->indxh=fopen($path.'/'.$name.'.indx','r+'); if (!file_exists($path.'/'.$name.'.lft')) $this->lfth=fopen($this->path.'/'.$name.'.lft','w+'); else $this->lfth=fopen($this->path.'/'.$name.'.lft','r+'); if ($this->mod=='w') { $this->lckh=fopen($this->path.'/'.$name.'.lck','w'); flock($this->lckh,2); fwrite($this->lckh,'lck');//lock the datebase } $rcd=$this->getRcd(0); $this->rcdCnt=$rcd[id]; $this->maxID=$rcd[loc]; $this->DBend=$rcd[len]; $rcd=$this->getLeft(0); $this->leftCnt=$rcd[loc]; } else $this->isError=1; } function setRcd($rid,$id,$loc,$len) { fseek($this->indxh,$rid*12); $str=pack('III',$id,$loc,$len); fwrite($this->indxh,$str,12); } function getRcd($rid) { fseek($this->indxh,$rid*12); $str=fread($this->indxh,12); $rcd=array(); $rcd[id]=str2int($str); $rcd[loc]=str2int(substr($str,4,4)); $rcd[len]=str2int(substr($str,8,4)); return $rcd; } function setLeft($lid,$loc,$len) { fseek($this->lfth,$lid*8); $str=pack('II',$loc,$len); fwrite($this->lfth,$str,8); } function getLeft($lid) { fseek($this->lfth,$lid*8); $str=fread($this->lfth,8); $rcd[loc]=str2int($str); $rcd[len]=str2int(substr($str,4,4)); return $rcd; } function clear() { $this->setRcd(0,0,0,0); $this->setLeft(0,0,0); } function close() { @fclose($this->dbh); @fclose($this->indxh); @fclose($this->lfth); @fclose($this->lckh); } function seekSpace($len) { $res=array('loc'=>0,'len'=>0); if ($this->leftCnt<1) return $res; $find=0; $min=1000000; for ($i=$this->leftCnt;$i>0;$i--) { $res=$this->getLeft($i); if ($res[len]==$len) {$find=$i;break;} else if($res[len]>$len) { if ($res[len]-$len<$min) { $min=$res[len]-$len; $find=$i; } } } if ($find) { $res=$this->getLeft($find); if ($res[len]<2*$len) { fseek($this->lfth,($find+1)*8); $str=fread($this->lfth,($this->leftCnt-$find)*8); fseek($this->lfth,$find*8); fwrite($this->lfth,$str); $this->leftCnt--; $this->setLeft(0,$this->leftCnt,0); return $res; } else { $rs=array(); $rs[loc]=$res[loc]; $rs[len]=$len; $res[loc]+=$len; $this->setLeft($find,$res[loc],$res[len]-$len); return $rs; } } else//fail { $res[len]=0; return $res; } } function insert($content,$len=0)//return with record id { $res=array('loc'=>0); if ($this->mod!='w') return 0; if (!$len) $len=strlen($content); if ($len<$this->minLen) $len=$this->minLen; if ($this->leftCnt) $res=$this->seekSpace($len); if (!$res[len]) { $res[loc]=$this->DBend; $res[len]=$len; } if ($res[loc]+$res[len]>$this->DBend) $this->DBend=$res[loc]+$res[len]; //echo $this->DBend.''; $this->maxID++; $this->rcdCnt++; $this->setRcd(0,$this->rcdCnt,$this->maxID,$this->DBend); $this->setRcd($this->rcdCnt,$this->maxID,$res[loc],$res[len]); fseek($this->dbh,$res[loc]); fwrite($this->dbh,$content,$len); return $this->maxID; } function findByID($id) { if ($id<1 or $id>$this->maxID or $this->rcdCnt<1) return 0; $left=1; $right=$this->rcdCnt; while($left<$right) { $mid=(int)(($left+$right)/2); if ($mid==$left or $mid==$right) break; $rcd=$this->getRcd($mid); if ($rcd[id]==$id) return $mid; else if($id<$rcd[id]) $right=$mid; else $left=$mid; } //$rcd=$this->getRcd($mid); //if ($rcd[id]==$id) return $mid; $rcd=$this->getRcd($left); if ($rcd[id]==$id) return $left; $rcd=$this->getRcd($right); if ($rcd[id]==$id) return $right; return 0; } function delete($id) { if ($this->mod!='w') return 0; $rid=$this->findByID($id); if (!$rid) return; $res=$this->getRcd($rid); fseek($this->indxh,($rid+1)*12); $str=fread($this->indxh,($this->rcdCnt-$i)*12); fseek($this->indxh,$rid*12); fwrite($this->indxh,$str); $this->rcdCnt--; if ($res[loc]+$res[len]==$this->DBend) { $this->DBend=$res[loc]; $this->setRcd(0,$this->rcdCnt,$this->maxID,$this->DBend); } else { $this->setRcd(0,$this->rcdCnt,$this->maxID,$this->DBend); $this->leftCnt++; $this->setLeft(0,$this->leftCnt,0); $this->setLeft($this->leftCnt,$res[loc],$res[len]); } } function update($id,$newcontent,$len=0) { if ($this->mod!='w') return; $rid=$this->findByID($id); if (!$rid) return; if (!$len) $len=strlen($newcontent); $rcd=$this->getRcd($rid); if ($rcd[len]<$len) { $this->leftCnt++; $this->setLeft(0,$this->leftCnt,0); $this->setLeft($this->leftCnt,$rcd[loc],$rcd[len]); $rcd[loc]=$this->DBend; $rcd[len]=$len; $this->DBend+=$len; $this->setRcd(0,$this->rcdCnt,$this->maxID,$this->DBend); $this->setRcd($rid,$rcd[id],$rcd[loc],$rcd[len]); } fseek($this->dbh,$rcd[loc]); fwrite($this->dbh,$newcontent,$len); //echo $id.''.$content.''.$len; } function selectByRid($rid) { $res=array('id'=>0,'content'=>''); if ($rid<1 or $rid>$this->rcdCnt) return $res; else $rcd=$this->getRcd($rid); $res[id]=$rcd[id]; $res[len]=$rcd[len]; fseek($this->dbh,$rcd[loc]); $res[content]=fread($this->dbh,$rcd[len]); return $res; } function select($id) { return $this->selectByRid($this->findByID($id)); } function backup() { copy($this->path.'/'.$this->name.'.tdb',$this->path.'/'.$this->name.'.tdb.bck'); copy($this->path.'/'.$this->name.'.indx',$this->path.'/'.$this->name.'.indx.bck'); copy($this->path.'/'.$this->name.'.lft',$this->path.'/'.$this->name.'.lft.bck'); } function recover() { copy($this->path.'/'.$this->name.'.tdb.bck',$this->path.'/'.$this->name.'.tdb'); copy($this->path.'/'.$this->name.'.indx.bck',$this->path.'/'.$this->name.'.indx'); copy($this->path.'/'.$this->name.'.lft.bck',$this->path.'/'.$this->name.'.lft'); } } ?>
作者的2.0版,生成dbm:
class TxtDB { var $name='';//文本数据库名 var $path=''; var $minLen=20; var $isError; var $dbh; var $indxh; var $lfth; var $lckh; var $rcdCnt=0; var $maxID=0; var $leftCnt=0; var $DBend=0; var $mod='w'; function TxtDB($name,$mod='w',$path='bpns_dbm') { $this->name=$name; $this->path=$path.'/'.$name; $this->isError=0; $this->mod=$mod; $path=$this->path; if ($name!='') { @mkdir($this->path,0777); if (!file_exists($path.'/'.$name.'.tdb')) $this->dbh=fopen($this->path.'/'.$name.'.tdb','w+'); else $this->dbh=fopen($path.'/'.$name.'.tdb','r+'); if (!file_exists($path.'/'.$name.'.indx')) $this->indxh=fopen($this->path.'/'.$name.'.indx','w+'); else $this->indxh=fopen($path.'/'.$name.'.indx','r+'); if (!file_exists($path.'/'.$name.'.lft')) $this->lfth=fopen($this->path.'/'.$name.'.lft','w+'); else $this->lfth=fopen($this->path.'/'.$name.'.lft','r+'); if ($this->mod=='w') { $this->lckh=fopen($this->path.'/'.$name.'.lck','w'); flock($this->lckh,2); fwrite($this->lckh,'lck');//lock the datebase } $rcd=$this->getRcd(0); $this->rcdCnt=$rcd[id]; $this->maxID=$rcd[loc]; $this->DBend=$rcd[len]; $rcd=$this->getLeft(0); $this->leftCnt=$rcd[loc]; } else $this->isError=1; } function setRcd($rid,$id,$loc,$len) { fseek($this->indxh,$rid*12); $str=pack('III',$id,$loc,$len); fwrite($this->indxh,$str,12); } function getRcd($rid) { fseek($this->indxh,$rid*12); $str=fread($this->indxh,12); $rcd=array(); $rcd[id]=str2int($str); $rcd[loc]=str2int(substr($str,4,4)); $rcd[len]=str2int(substr($str,8,4)); return $rcd; } function setLeft($lid,$loc,$len) { fseek($this->lfth,$lid*8); $str=pack('II',$loc,$len); fwrite($this->lfth,$str,8); } function getLeft($lid) { fseek($this->lfth,$lid*8); $str=fread($this->lfth,8); $rcd[loc]=str2int($str); $rcd[len]=str2int(substr($str,4,4)); return $rcd; } function clear() { $this->setRcd(0,0,0,0); $this->setLeft(0,0,0); } function close() { @fclose($this->dbh); @fclose($this->indxh); @fclose($this->lfth); @fclose($this->lckh); } function seekSpace($len) { $res=array('loc'=>0,'len'=>0); if ($this->leftCnt<1) return $res; $find=0; $min=1000000; for ($i=$this->leftCnt;$i>0;$i--) { $res=$this->getLeft($i); if ($res[len]==$len) {$find=$i;break;} else if($res[len]>$len) { if ($res[len]-$len<$min) { $min=$res[len]-$len; $find=$i; } } } if ($find) { $res=$this->getLeft($find); if ($res[len]<2*$len) { fseek($this->lfth,($find+1)*8); $str=fread($this->lfth,($this->leftCnt-$find)*8); fseek($this->lfth,$find*8); fwrite($this->lfth,$str); $this->leftCnt--; $this->setLeft(0,$this->leftCnt,0); return $res; } else { $rs=array(); $rs[loc]=$res[loc]; $rs[len]=$len; $res[loc]+=$len; $this->setLeft($find,$res[loc],$res[len]-$len); return $rs; } } else//fail { $res[len]=0; return $res; } } function insert($content,$len=0)//return with record id { $res=array('loc'=>0); if ($this->mod!='w') return 0; if (!$len) $len=strlen($content); if ($len<$this->minLen) $len=$this->minLen; if ($this->leftCnt) $res=$this->seekSpace($len); if (!$res[len]) { $res[loc]=$this->DBend; $res[len]=$len; } if ($res[loc]+$res[len]>$this->DBend) $this->DBend=$res[loc]+$res[len]; //echo $this->DBend.''; $this->maxID++; $this->rcdCnt++; $this->setRcd(0,$this->rcdCnt,$this->maxID,$this->DBend); $this->setRcd($this->rcdCnt,$this->maxID,$res[loc],$res[len]); fseek($this->dbh,$res[loc]); fwrite($this->dbh,$content,$len); return $this->maxID; } function findByID($id) { if ($id<1 or $id>$this->maxID or $this->rcdCnt<1) return 0; $left=1; $right=$this->rcdCnt; while($left<$right) { $mid=(int)(($left+$right)/2); if ($mid==$left or $mid==$right) break; $rcd=$this->getRcd($mid); if ($rcd[id]==$id) return $mid; else if($id<$rcd[id]) $right=$mid; else $left=$mid; } //$rcd=$this->getRcd($mid); //if ($rcd[id]==$id) return $mid; $rcd=$this->getRcd($left); if ($rcd[id]==$id) return $left; $rcd=$this->getRcd($right); if ($rcd[id]==$id) return $right; return 0; } function delete($id) { if ($this->mod!='w') return 0; $rid=$this->findByID($id); if (!$rid) return; $res=$this->getRcd($rid); fseek($this->indxh,($rid+1)*12); $str=fread($this->indxh,($this->rcdCnt-$i)*12); fseek($this->indxh,$rid*12); fwrite($this->indxh,$str); $this->rcdCnt--; if ($res[loc]+$res[len]==$this->DBend) { $this->DBend=$res[loc]; $this->setRcd(0,$this->rcdCnt,$this->maxID,$this->DBend); } else { $this->setRcd(0,$this->rcdCnt,$this->maxID,$this->DBend); $this->leftCnt++; $this->setLeft(0,$this->leftCnt,0); $this->setLeft($this->leftCnt,$res[loc],$res[len]); } } function update($id,$newcontent,$len=0) { if ($this->mod!='w') return; $rid=$this->findByID($id); if (!$rid) return; if (!$len) $len=strlen($newcontent); $rcd=$this->getRcd($rid); if ($rcd[len]<$len) { $this->leftCnt++; $this->setLeft(0,$this->leftCnt,0); $this->setLeft($this->leftCnt,$rcd[loc],$rcd[len]); $rcd[loc]=$this->DBend; $rcd[len]=$len; $this->DBend+=$len; $this->setRcd(0,$this->rcdCnt,$this->maxID,$this->DBend); $this->setRcd($rid,$rcd[id],$rcd[loc],$rcd[len]); } fseek($this->dbh,$rcd[loc]); fwrite($this->dbh,$newcontent,$len); //echo $id.''.$content.''.$len; } function selectByRid($rid) { $res=array('id'=>0,'content'=>''); if ($rid<1 or $rid>$this->rcdCnt) return $res; else $rcd=$this->getRcd($rid); $res[id]=$rcd[id]; $res[len]=$rcd[len]; fseek($this->dbh,$rcd[loc]); $res[content]=fread($this->dbh,$rcd[len]); //$res[rid]=$rid; return $res; } function select($id) { return $this->selectByRid($this->findByID($id)); } function backup() { copy($this->path.'/'.$this->name.'.tdb',$this->path.'/'.$this->name.'.tdb.bck'); copy($this->path.'/'.$this->name.'.indx',$this->path.'/'.$this->name.'.indx.bck'); copy($this->path.'/'.$this->name.'.lft',$this->path.'/'.$this->name.'.lft.bck'); } function recover() { copy($this->path.'/'.$this->name.'.tdb.bck',$this->path.'/'.$this->name.'.tdb'); copy($this->path.'/'.$this->name.'.indx.bck',$this->path.'/'.$this->name.'.indx'); copy($this->path.'/'.$this->name.'.lft.bck',$this->path.'/'.$this->name.'.lft'); } } ?>
