这里是源程序01:
<?
class fileDB
{
//数据库系统工作的基本目录;
var $dbdir;
//数据库主文件;
var $dbfile;
//数据库辅助文件,用于存放数据属性和主键已经他们在主文件中的指针情况;
var $dbfilelist;
//数据库用户文件,存放数据库用户名和密码;
var $dbuserfile;
//数据库名;
var $database;
//表的主文件名;
var $tablefile;
//表的辅文件名;
var $tableman;
//表的删除空间管理文件名;
var $tabledel;
//整个数据库的用户名;
var $user;
//用户的密码;
var $pw;
//用户是否连接到数据库;
var $isConnectDB;
//用户是否连接到表;
var $isConnectTable;
//用户是否登陆;
var $isLogin; //用户函数;
////////////////////////////////////////////////////////////////////////////////////////
function fileDB()
{
$this->dbdir="./fileDatabase/";
$this->dbuserfile=$this->dbdir."admin.fdb";
echo "<p align=center>欢迎使用 File Database 2.0 版本<br>所有版权归麦唐工作室所有<br>leeo开发。</p><br>";
}
//用户初始化,包括建立基本数据库工作目录,建立用户文件,写入用户名和用户密码;
//用户名和密码最长不能超过20位;
function init($user,$pw)
{
$this->user=$user;
$this->pw=$pw;
if(!is_dir($this->dbdir))
{
mkdir($this->dbdir,0700);
$this->formatdata("a",20,$this->user);
$this->formatdata("z",20,$this->pw);
$this->encrypt($this->user);
$this->encrypt($this->pw);
$fp=fopen($this->dbuserfile,"w");
fwrite($fp,$this->user);
fwrite($fp,$this->pw);
fclose($fp);
}
}
//判断是否合法用户登陆;
function login($user,$pw)
{
$this->formatdata("a",20,$user);
$this->formatdata("z",20,$pw);
$this->encrypt($user);
$this->encrypt($pw);
$fp=fopen($this->dbuserfile,"r");
$fuser=fread($fp,20);
$fpw=fread($fp,20);
fclose($fp);
if(strcmp($fuser,$user)!=0)
{
echo "此用户不存在!<br>";
$this->isLogin=false;
return;
}
if(strcmp($pw,$fpw)!=0)
{
echo "密码错误!<br>";
$this->isLogin=false;
return;
}
$this->isLogin=true;
} //建立数据库,即在基本目录中建立一个以数据库名命名的文件夹;
function createDB($database)
{
if($this->isLogin!=true)
{
echo "用户登陆错误!<br>";
return false;
}
$database=$this->dbdir.$database;
if(is_dir($database))
{
echo basename($this->database)."数据库已经存在!<br>";
return false;
}
mkdir($database,0700);
return true;
} //返回当前操作的数据库名;
function getDatabase()
{
if($this->isConnectDB!=true)
{
echo "目前没有连接到任何数据库!<br>";
return false;
}
$database=basename($this->database);
return $database;
} //连接到数据库;
function connectDB($database)
{
if($this->isLogin!=true)
{
echo "用户登陆错误!<br>";
return false;
}
$this->database=$this->dbdir.$database;

if($this->isDatabase($this->database))
$this->isConnectDB=true;
else
{
echo "连接数据库错误!<br>";
$this->isConnectDB=false;
}
}

//关闭数据库;
function closeDB()
{
$this->database=false;
$this->isConnectDB=false;
$this->isLogin=false;
} //删除数据库;
//删除数据库时必须保证其中没有任何表;
function dropDB()
{
if(!$this->isConnectDB)
return false;
if(rmdir($this->database)==0)
{
echo "当前库下还有表或者用户不具备相应权限!<br>";
return false;
}
$this->closeDB();
return true;
} //在给出的数据库$database下建一个表$table。
//$ele为数组形式的属性项,$elesize为数组形式的属性项大小,和$ele是对应的。
//$table辅文件中第一位为0表示本表未锁,为1表示本表以锁,
//2~4三位表示本表中属性项的个数,
//4~7四位表示本表中元组的个数,
//其中属性项为20位,属性项大小描述的为5位,一个属性描述总长为25位。
function createTable($table,$tuple,$tupleSize)
{
if($this->isLogin!=true)
{
echo "用户登陆错误!<br>";
return false;
}
if($this->isConnectDB!=true)
{
echo "用户连接数据库错误!<br>";
return false;
}
$tablefile=$this->database."/".$table.".fdb";
$tableman=$this->database."/".$table."_man.fdb";
$tabledel=$this->database."/".$table."_del.fdb";
if(is_file($tablefile))
{
echo basename($tablefile)."表已经存在!<br>";
return false;
}
//判断提供的属性和属性大小数组变量是否合法。
if(!is_array($tuple))
{
echo "提供的属性项不是数组形式!<br>";
return false;
}
if(!is_array($tupleSize))
{
echo "提供的属性项大小不是数组形式!<br>";
return false;
}
//判断属性和属性大小数组是否匹配。
if(count($tuple)!=count($tupleSize))
{
echo "属性数组和属性大小数组不匹配!<br>";
return false;
}
//取得属性数组中元素个数;
else
{
$elenum=count($tuple);
$this->formatdata("0",3,$elenum);
}
$fp=fopen($tablefile,"w");
fclose($fp);
$fp=fopen($tabledel,"w");
$fp=fopen($tableman,"w");
fwrite($fp,"0");
fwrite($fp,$elenum);
fwrite($fp,"0000");
for($i=0;$i<$elenum;$i++)
{
$this->formatdata(" ",20,$tuple[$i]);
$this->formatdata("0",5,$tupleSize[$i]);
fwrite($fp,$tuple[$i]);
fwrite($fp,$tupleSize[$i]);
}
fclose($fp);
}

解决方案 »

  1.   

    这是源程序02: //返回目前操作的表名;
    function getTable()
    {
    if($this->isConnectTable!=true)
    {
    echo "目前没有连接到任何表!<br>";
    return false;
    }
    $table=basename($this->tablefile);
    $table=substr($table,0,strlen($table)-4);
    return $table;
    } //返回数据库中所有的表;
    function tableList()
    {
    if(!$this->isConnectDB)
    {
    echo "连接数据库错误!<br>";
    return false;
    }
    $base=dir($this->database);
    for($i=0;$t[$i]=$base->read();$i++)
    {
    if($i>1)
    {
    if(!strpos($t[$i],"_"))
    if(!strpos($t[$i],"bak"))
    $table[$i-2]=$t[$i];
    }
    }
    $base->close();
    return $table;
    } //连接到表
    function connectTable($table)
    {
    if($this->isConnectDB!=true)
    {
    echo "用户还未连接到数据库!<br>";
    return false;
    }
    $this->tablefile=$this->database."/".$table.".fdb";
    $this->tableman=$this->database."/".$table."_man.fdb";
    $this->tabledel=$this->database."/".$table."_del.fdb";
    if($this->isTable($this->tableman))
    $this->isConnectTable=true;
    else
    $this->isConnectTable=false;
    } //关闭表;
    function closeTable()
    {
    $this->tablefile=false;
    $this->tableman=false;
    $this->tabledel=false;
    $this->isConnectTable=false;
    } //删除表;
    //删除表后会关闭数据库连接,如果要进行其他操作需重新连接数据库和表;
    //要彻底删除一个表要删除它的备份,然后删除它本身;
    function dropTable()
    {
    if(!$this->isConnectTable)
    {
    echo "还未连接到表!<br>";
    return false;
    }
    if($this->seeLock()!=0)
    $this->wait();
    unlink($this->tablefile);
    unlink($this->tableman);
    unlink($this->tabledel);
    $this->closeTable();
    $this->isConnectTable=false;
    }
    //删除备份表;
    function dropTablebak()
    {
    if(!$this->isConnectTable)
    {
    echo "还未连接到表!<br>";
    return false;
    }
    if($this->seeLock()==1)
    $this->wait();
    unlink($this->tablefile.".bak");
    unlink($this->tableman.".bak");
    unlink($this->tabledel.".bak");
    } //返回表中元组的个数;
    function countTuple()
    {
    if(!$this->isConnectTable)
    {
    echo "还未连接到表!<br>";
    return false;
    }
    if($this->seeLock()==1)
    $this->wait();
    $size=filesize($this->tableman);
    $attrNum=$this->countAttr();
    $count=($size-8-25*$attrNum)/8/$attrNum;
    return $count;
    } //统计表中的属性个数;
    function countAttr()
    {
    if(!$this->isConnectTable)
    {
    echo "还未连接到表!<br>";
    return false;
    }
    if($this->seeLock()==1)
    $this->wait();
    $fp=fopen($this->tableman,"r");
    fseek($fp,1);
    $elenum=(int)fread($fp,3);
    fclose($fp);
    return $elenum;
    } //以数组形式返回表中各属性项大小;
    function tableAttrsize()
    {
    if($this->seeLock()==1)
    $this->wait();
    $fp=fopen($this->tableman,"r");
    fseek($fp,8);
    $num=$this->countAttr();
    for($i=0;$i<$num;$i++)
    {
    fseek($fp,ftell($fp)+20);
    $eleSize[$i]=(int)fread($fp,5);
    }
    return $eleSize;
    } //取得表中的属性项,并以数组的形式输出;
    function selectAttr()
    {
    if(!$this->isConnectTable)
    {
    echo "还未连接到表!<br>";
    return false;
    }
    if($this->seeLock()==1)
    $this->wait();
    if(!$this->isConnectTable)
    return false;
    $fp=fopen($this->tableman,"r");
    fseek($fp,8);
    for($i=0;$i<$this->countAttr();$i++)
    {
    $Attr[$i]=trim(fread($fp,20));
    fseek($fp,ftell($fp)+5);
    }
    return $Attr;
    } //给表插入数据,$table是要操作的表名,$ele是数组形式要插入的数据名;
    //一次只能插入一行数据,即数组中元素个数要与表中属性项个数相等;
    //每个元组用8位记载本元组在$tablefile里的起始地址;
    //本函数执行时先给$tableman加锁防止其他操作读写本文件,当插入操作结束时解本表的锁;
    function insertTable($tuple)
    {
    $check=$this->insertTuplecheck($tuple);
    if($check==0)
    return false;
    $attrNum=$this->countAttr();
    $tupleSize=$this->tableAttrsize();
    $assNum=filesize($this->tabledel)/8/3;
    if($this->seeLock()!=0)
    $this->wait();
    $this->loginStart();
    $this->tableBak();
    $this->xLock();
    $mp=fopen($this->tableman,"a");
    if($check==1)
    {
    for($i=0;$i<$attrNum;$i++)
    {
    $this->formatdata(" ",$tupleSize[$i],$tuple[$i]);
    if($assNum>0)
    {
    $fp=fopen($this->tablefile,"r+");
    $dp=fopen($this->tabledel,"r");
    $ap=(int)fread($dp,8);
    fseek($fp,$ap);
    $dplast=fread($dp,filesize($this->tabledel));
    fclose($dp);
    $dp=fopen($this->tabledel,"w");
    fwrite($dp,$dplast);
    fclose($dp);
    }
    else
    $fp=fopen($this->tablefile,"a");
    fwrite($fp,$tuple[$i]);
    $tupleOr=ftell($fp)-strlen($tuple[$i]);
    $this->formatdata("0",8,$tupleOr);
    fwrite($mp,$tupleOr);
    fclose($fp);
    }
    }
    if($check==2)
    {
    if(count($tuple)>$assNum)
    {
    $b=$assNum-1;
    $goon=true;
    }
    else
    {
    $b=count($tuple)-1;
    $goon=false;
    }
    if($assNum>0)
    {
    $fp=fopen($this->tablefile,"r+");
    $dp=fopen($this->tabledel,"r");
    for($i=0;$i<$b;$i++)
    {
    for($j=0;$j<$attrNum;$j++)
    {
    $this->formatdata(" ",$tupleSize[$j],$tuple[$i][$j]);
    $sp=fread($dp,8);
    fseek($fp,(int)$sp);
    fwrite($fp,$tuple[$i][$j]);
    fwrite($mp,$sp);
    }
    }
    $dlast=fread($dp,filesize($this->tabledel));
    fclose($dp);
    $dp=fopen($this->tabledel,"w");
    fwrite($dp,$dlast);
    fclose($dp);
    fclose($fp);
    }
    if($assNum<=0||$goon==true)
    {
    $fp=fopen($this->tablefile,"a");
    if($goon==true)
    $s=$assNum;
    else
    $s=0;
    for($i=$s;$i<count($tuple);$i++)
    {
    for($j=0;$j<$attrNum;$j++)
    {
    $this->formatdata(" ",$tupleSize[$j],$tuple[$i][$j]);
    fwrite($fp,$tuple[$i][$j]);
    $tupleOr=ftell($fp)-strlen($tuple[$i][$j]);
    $this->formatdata("0",8,$tupleOr);
    fwrite($mp,$tupleOr);
    }
    }
    fclose($fp);
    }
    }
    fclose($mp);
    $this->unLock();
    $this->loginEnd();
    return true;
    }
      

  2.   

    这是源程序03:
    //取得表中顺序从$from到$to的元组;
    //返回值以数组形式返回;
    function selectTable($from,$to)
    {
    if(!$this->isConnectTable)
    return false;
    if(!$this->selectTablecheck($from,$to))
    return false;
    $attrCount=$this->countAttr();
    $tupleSize=$this->tableAttrsize();
    $sp=8+25*$attrCount+$from*$attrCount*8;
    if($this->seeLock()==1)
    $this->wait();
    $this->loginStart();
    $this->sLock();
    $fp=fopen($this->tablefile,"r");
    $mp=fopen($this->tableman,"r");
    fseek($mp,$sp);
    for($u=0,$i=$from;$i<=$to;$i++)
    {
    for($k=0;$k<$attrCount;$k++,$u++)
    {
    $ep=fread($mp,8);
    fseek($fp,$ep);
    $tuple[$u]=trim(fread($fp,$tupleSize[$k]));
    }
    }
    fclose($fp);
    fclose($mp);
    $this->unLock();
    $this->loginEnd();
    return $tuple;
    }
    //把相应属性列的数据项以数组形式返回。参数代表元组的序号。失败返回false。
    function selectTableByAttr($Attr,$from,$to)
    {
    if(!$this->isConnectTable)
    {
    echo "连接表错误!<br>";
    return false;
    }
    $attr=$this->selectAttr();
    $attrNum=$this->countAttr();
    for($i=0;$i<$attrNum;$i++)
    {
    if($Attr==$attr[$i])
    {
    $have=true;
    $attrOrd=$i;
    }
    }
    if(!$have)
    {
    echo "表中没有 ".$Attr." 这个属性!<br>";
    return false;
    }
    if(!$this->selectTablecheck($from,$to))
    return false;
    $sp=8+25*$attrNum+$from*$attrNum*8;
    $dis=$attrOrd*8;
    $tupleSize=$this->tableAttrsize();
    if($this->seeLock()==1)
    $this->wati();
    $this->loginStart();
    $this->sLock();
    $fp=fopen($this->tablefile,"r");
    $mp=fopen($this->tableman,"r");
    fseek($mp,$sp);
    for($u=0,$i=$from;$i<=$to;$i++,$u++)
    {
    fseek($mp,ftell($mp)+$dis);
    $ep=fread($mp,8);
    fseek($fp,$ep);
    $tuple[$u]=trim(fread($fp,$tupleSize[$attrOrd]));
    }
    fclose($fp);
    fclose($mp);
    $this->unLock();
    $this->loginEnd();
    return $tuple;
    }
    //删除表中的元组,从$from到$to范围,参数代表元组在表中的序号。
    function dropTuple($from,$to)
    {
    if(!$this->isConnectTable)
    return false;
    if(!$this->selectTablecheck($from,$to))
    return false;
    $attrCount=$this->countAttr();
    $eleSize=$this->tableAttrsize();
    $sp=8+25*$attrCount+$from*$attrCount*8;
    if($this->seeLock()!=0)
    $this->wait();
    $this->tableBak();
    $this->loginStart();
    $this->xLock();
    $mplen=$attrCount*8*($to-$from+1);
    $mp=fopen($this->tableman,"r+");
    $dp=fopen($this->tabledel,"r+");
    fseek($mp,$sp);
    for($i=$from;$i<=$to;$i++)
    {
    for($k=0;$k<$attrCount;$k++)
    {
    $ep=fread($mp,8);
    fwrite($dp,$ep);
    }
    }
    fclose($mp);
    fclose($dp);
    $mp=fopen($this->tableman,"r");
    $mp1=fread($mp,$sp);
    fseek($mp,$sp+$mplen);
    $mp2=fread($mp,filesize($this->tableman));
    fclose($mp);
    unlink($this->tableman);
    $mp=fopen($this->tableman,"w");
    fwrite($mp,$mp1);
    fwrite($mp,$mp2);
    fclose($mp);
    $this->unLock();
    $this->loginEnd();
    }
    //修改元组其中某个数据项,$tuple是元组在表中的序号,$order是该元组的第几个数据项。
    function alterTuple($tuple,$order,$content)
    {
    if(!$this->isConnectTable)
    {
    echo "还未连接到表!<br>";
    return false;
    }
    $attrNum=$this->countAttr();
    $tupleNum=$this->countTuple();
    $attrSize=$this->tableAttrsize();
    if($tuple>=$tupleNum||$tuple<0)
    {
    echo "表中没有这个元组!<br>";
    return false;
    }
    if($order>=$attrNum||$order<0)
    {
    echo "元组中没有这个数据项!<br>";
    return false;
    }
    $start=8+25*$attrNum+$tuple*$attrNum*8+$order*8;
    if(strlen($content)>$attrSize[$order])
    {
    echo "插入的内容和这个数据项的长度要求不符!<br>";
    return false;
    }
    $this->formatdata(" ",$attrSize[$order],$content);
    if($this->seeLock()!=0)
    $this->wait();
    $this->tableBak();
    $this->loginStart();
    $this->xLock();
    $mp=fopen($this->tableman,"r");
    $fp=fopen($this->tablefile,"r+");
    fseek($mp,$start);
    $cp=fread($mp,8);
    fseek($fp,$cp);
    fwrite($fp,$content);
    fclose($mp);
    fclose($fp);
    $this->unLock();
    $this->loginEnd();
    } //内部函数
    ////////////////////////////////////////////////////////////////////////////////////////////////
    //操作开始写操作日志;
    function loginStart()
    {
    $lp=fopen($this->tablefile.".log","w");
    $time=date("YmdHis");
    fwrite($lp,$time);
    fclose($lp);
    }
    //操作结束后删除日志;
    function loginEnd()
    {
    unlink($this->tablefile.".log");
    }
    //等待函数,判断此时表是否加锁,如果加的锁和要进行的操作不相容,等待。
    function wait()
    {
    $away=false;
    while($away!=true)
    {
    if(is_file($this->tablefile.".log"))
    {
    $now=date("YmdHis");
    $lp=fopen($this->tablefile.".log","r");
    $time=fread($lp,14);
    fclose($lp);
    if(($now-$time)>15)
    {
    $this->tableResume(1);
    $away=true;
    }
    }
    else
    $away=true;
    }
    }
    //测试表是否被锁;
    function seeLock()
    {
    $fp=fopen($this->tableman,"r");
    $lock=fread($fp,1);
    fclose($fp);
    return $lock;
    }
    //X锁表;
    function xLock()
    {
    $fp=fopen($this->tableman,"r+");
    fwrite($fp,"1");
    fclose($fp);
    }
      

  3.   

    佩服佩服专业的有XML,老的有dbase/filepro,不知道你比那个强?不要重新发明轮子了
    本地数据库已经有很多了
      

  4.   

    各位似乎有点...
    数据库毕竟只是一种选择,mysql是另外收费的,做个留言本就没有必要动他。支持一下。这是我做的,http://3ants.org/txtdb
      

  5.   

    在有些申请的空间中,资源供应商会有限制,比如数据库中不能存留言板和bbs的数据。所以我做了这个可以面对这些问题。
    我觉得作为一个像我这样的初学者,对于这些数据结构实现的问题多想想还是有好处的。如果我们想推动什么更进步,首先我们要了解他,对吧。我就是在了解他。呵呵。
      

  6.   

    具体的使用方法我还有关于这个主题的第二个帖子,叫“接File Database的源程序04”。里面给出了简单的示例,如果还需要具体的使用方法可以发邮件到[email protected]来。欢迎大家。
      

  7.   

    提出一点建议,仅供参考:array selectTable($from,$to)
    查询语句只有这一个么?似乎不太够
    WHERE子句无法实现
      

  8.   

    查询和一些其他功能确实还很不完善,没办法和专业的数据库比。
    其实我如果再做where的话也是基于selecttable作的。由于这个东西就写了3天,所以没写太多。
    其实这个是为一个小的社区系统做的。我以前做的bbs也是基于文本的。不过这一次把数据处理这一块分离出来了。作为一个公共模块,在bbs,个人留言板,论坛等一些模块里使用了。
    至于商业价值,我个人也认为没有。商业似乎应该更讲求安全和效率。这些我这个都没有。
      

  9.   

    严重同意 rockypan(书山有路vs学海无涯) 
    用心就好了
      

  10.   

    如果直接用留言板读写文本,那我再做一个bbs是不是又要再写一遍读写文本的代码。
    那我又做了一个公告发布是不是要再写遍。如果我做了一个整合了这些功能的东西,并要求他们之间互相通信,把文本读写部分分离出来不好么?