• 转贴一篇 自定义数据库 希望对你有帮助


    //---------------------------------------------------------------------------
    //(R)CopyRight KivenSoft International ,inc 1999
    //单元名称:数据库单元
    //程序名称:电子书库
    //作    者:李会文
    //开始时间:1998.07.28
    //最后修改:1999.07.22
    //备注:此单元定义了SRM文件的读写接口
    //---------------------------------------------------------------------------
    unit SrmUnit;

    interface

    uses
      Windows,SysUtils,Classes, SrmConst;


    type
    PCharArray=^TCharArray;
    TCharArray=array[0..0] of char;
    PDwordArray=^TDwordArray;
    TDwordArray=array[0..0] of DWORD;
    PIntArray=^TIntArray;
    TIntArray=array[0..0] of integer;

    PTreeData=^TTreeData;
    TTreeData=record        //索引信息
      Pos: longint;
      DataType: longint;
    end;
    PTdArray=^TTdArray;
    TTdArray=array[0..0] of TTreeData;

    PFileHead=^TFileHead;
    TFileHead=record
      OpenFlag      :Longint;                      //数据库打开标志
      LastViewPos   :longint;                   //关闭时的位置
      IndexPos      :longint;                   //索引位置
      EditDate      :TDateTime;                 //最后修改日期
      Key           :DWORD;                     //密钥
      Password      :array[0..11] of char;      //口令
      Author        :array[0..15] of char;      //作者
      BuildDate     :TDateTime;                 //建库日期
      DataType      :longint;                   //数据库格式
      DataFlag      :array[0..7] of char;       //数据库标志
      Version       :longint;                   //数据库版本
      BookMerg      :array[0..9] of longint;    //10个书签
      Keep          :longint;                   //保留字段
    end;

    //DataType 0:Index    1:Normal Dir     2:Notmal TXT    3:Normal HTML
    PIndexHead=^TIndexHead;
    TIndexHead=record
      DataType      :longint;                   //段类型
      Key           :DWORD;                     //密钥
      Count         :longint;                   //标题数量
      Size          :longint;                   //标题长度
      Keep          :longint;                   //保留字段
    end;

    PDataHead=^TDataHead;
    TDataHead=record
      DataType      :longint;                   //段类型
      Author        :array[0..15] of char;      //作者
      PubDate       :TDateTime;                 //收录日期
      Key           :DWORD;                     //密钥
      Num           :longint;                   //附件数量
      SearchKey     :array[0..51] of char;      //关键词
      Password      :array[0..11] of char;      //口令
      Keep          :longint;                   //保留字段
    end;

    //------------------------------------------------------------------------
    TSrmObject=class
      private
        FChangeFlag         :boolean;   //在文件后有增加新信息的变量
        FDbChanged          :boolean;   //数据库属性有变动
        FIndexChanged       :boolean;   //索引有变动
        FItemHeadChanged    :boolean;   //标题头有变动
        FItemDataChanged    :boolean;   //标题内容有变动
        FFileHead           :TFileHead;
        FIndexHead          :TIndexHead;
        FDataHead           :TDataHead;
        FFileHandle         :integer;       //文件句柄
        FFileName           :string;
        FActivePos          :longint;       //当前读出内容的位置

        procedure Encypher(Cypher:DWORD;var Buf;Count:integer);
        procedure Decypher(Cypher:DWORD;var Buf;Count:integer);
        procedure CreateSrmFile;            //建立一个空数据库
        procedure SetDbChanged(Value:boolean);
        procedure SetIndexChanged(Value:boolean);
        procedure SetItemHeadChanged(Value:boolean);
        procedure SetItemDataChanged(Value:boolean);
      public
        property FileName:string read FFileName;
        property FileHead:TFileHead read FFileHead write FFileHead;
        property IndexHead:TIndexHead read FIndexHead write FIndexHead;
        property DataHead:TDataHead read FDataHead write FDataHead;
        property ActivePos:longint read FActivePos write FActivePos;
        property DbChanged:boolean read FDbChanged write SetDbChanged;
        property IndexChanged:boolean read FIndexChanged write SetIndexChanged;
        property ItemHeadChanged:boolean read FItemHeadChanged write SetItemHeadChanged;
        property ItemDataChanged:boolean read FItemDataChanged write SetItemDataChanged;

        constructor Create(Fn:string;Mode:Word);
        destructor Destroy;override;
        procedure Free;
        procedure SaveSrmFile;          //不关闭文件情况下保存文件
        procedure LoadIndex(Msh,Msd:TMemoryStream); //读索引
        procedure SaveIndex(Msh,Msd:TMemoryStream);//写索引
        class function IsSrmFile(var Fn:string):boolean;//判断是否是SRM格式数据库文件
        procedure ReadItemHead(Ps:longint);  //读数据段头
        procedure ReadItemData(DataStream:TMemoryStream);  //读数据段内容
        procedure EditItemHead(Ps:longint);    //修改数据头
        function AddItemHead:longint;          //写数据段头
        procedure AddItemData(DataStream:TMemoryStream); //写数据段内容
        function GetItemPassword(Ps:longint):string; //得某标题口令
     end;
    //------------------------------------------------------------------------


    implementation

    //------------------------------------------------------------------------
    procedure TSrmObject.Encypher(Cypher:DWORD;var Buf;Count:integer);
    var
      i:integer;
    begin
      Cypher:=not Cypher;
      Dec(Count);
      for i:=0 to Count do
        TDwordArray(Buf)[i]:=TDwordArray(Buf)[i] xor Cypher;
    end;

    procedure TSrmObject.Decypher(Cypher:DWORD;var Buf;Count:integer);
    var
      i:integer;
    begin
      Cypher:=not Cypher;
      Dec(Count);
      for i:=0 to Count do
        TDwordArray(Buf)[i]:=TDwordArray(Buf)[i] xor Cypher;
    end;
    //------------------------------------------------------------------------

    procedure TSrmObject.CreateSrmFile;    //建立一个空数据库
    var
      i:integer;
    begin
        FFileHandle:=FileCreate(FFileName);
        if FFileHandle=-1 then raise Exception.Create(csCanNotCreate);
        //添充缺省信息头
        with FFileHead do
        begin
          OpenFlag:=0;
          LastViewPos:=0;
          IndexPos:=sizeof(TFileHead);
          EditDate:=Now;
          Key:=GetTickCount;
          Password[0]:=#0;
          Author[0]:=#0;
          BuildDate:=EditDate;
          DataType:=0;
          Version:=3;
          Keep:=0;
          DataFlag[0]:='K';
          DataFlag[1]:='i';
          DataFlag[2]:='v';
          DataFlag[3]:='e';
          DataFlag[4]:='n';
          for i:=0 to 9 do BookMerg[i]:=-1;
        end;
        //添充缺省索引
        with FIndexHead do
        begin
          DataType:=0;
          Key:=GetTickCount;
          Count:=0;
          Size:=0;
          Keep:=0;
        end;
        //加密写入文件后解密
        with FFileHead do
        begin
          Encypher(Key,Author,4);
          Encypher(Key,Password,3);
          FileWrite(FFileHandle,FFileHead,sizeof(TFileHead));
          FileWrite(FFileHandle,FIndexHead,sizeof(TIndexHead));
          Decypher(Key,Author,4);
          Decypher(Key,Password,3);
        end;
    end;

    constructor TSrmObject.Create(Fn:string;Mode:Word);
    begin
      FFileName:=Fn;
      FChangeFlag:=false;
      FDbChanged:=false;
      FIndexChanged:=false;
      FItemHeadChanged:=false;
      FItemDataChanged:=false;
      FDataHead.Keep:=0;
      //打开文件时读文件头,否则建新文件
      if Mode=fmOpenReadWrite then
      begin
        FFileHandle:=FileOpen(FFileName,fmOpenReadWrite);
        FileRead(FFileHandle,FFileHead,sizeof(TFileHead));
        with FFileHead do
        begin
          Decypher(Key,Password,3);
          Decypher(Key,Author,4);
        end;
      end
      else if Mode=fmCreate then
      begin
        CreateSrmFile;
      end;
    end;

    destructor TSrmObject.Destroy;
    begin
      if FFileHandle<>-1 then
      begin
        FileClose(FFileHandle);  //关闭文件
        FFileHandle:=-1;
      end;
      inherited;
    end;

    procedure TSrmObject.Free;
    begin
      if Assigned(self) then Destroy;
    end;

    procedure TSrmObject.SaveSrmFile;
    begin
      //写入更新后的文件头
      with FFileHead do
      begin
        FileSeek(FFileHandle,0,0);
        EditDate:=Now;
        Key:=GetTickCount;
        Encypher(Key,Password,3);
        Encypher(Key,Author,4);
        FileWrite(FFileHandle,FFileHead,sizeof(TFileHead));
        Decypher(Key,Password,3);
        Decypher(Key,Author,4);
      end;
    end;

    class function TSrmObject.IsSrmFile(var Fn:string):boolean;
    var
      Fh: TFileHead;
      Fs: TFileStream;
    begin
      Result:=false;
      Fs:=TFileStream.Create(Fn,fmOpenRead);
      //根据文件长度判断
      with Fs do
      begin
        if (Size<(sizeof(TFileHead)+sizeof(TIndexHead))) then
        begin
          Free;
          Result:=false;
          Exit;
        end;
        Read(Fh,sizeof(TFileHead));
        Free;
      end;
      //根据文件标志判断
      with Fh do
      begin
        if ( (DataFlag[0]='K') and (DataFlag[1]='i') and
            (DataFlag[2]='v') and (DataFlag[3]='e') and
            (DataFlag[4]='n') ) then
          Result:=true;
      end;
    end;

    procedure TSrmObject.LoadIndex(Msh,Msd:TMemoryStream);
    begin
      //读出索引头
      FileSeek(FFileHandle,FFileHead.IndexPos,0);
      FileRead(FFileHandle,FIndexHead,sizeof(TIndexHead));
      //处理索引长度为0的状况,否则读出具体索引
      if (FIndexHead.Size=0) then
      begin
        Msh.SetSize(0);
        Msd.SetSize(0);
      end
      else
      begin
        Msh.SetSize(FIndexHead.Size);
        Msd.SetSize(FIndexHead.Count*sizeof(longint)*2);
        FileRead(FFileHandle,Msh.Memory^,Msh.Size);
        FileRead(FFileHandle,Msd.Memory^,Msd.Size);
        Decypher(FIndexHead.Key,Msh.Memory^,Msh.Size div 4);
      end;
    end;

    procedure TSrmObject.SaveIndex(Msh,Msd:TMemoryStream);
    begin
      if FChangeFlag then  //增加过新内容时
        FFileHead.IndexPos:=FileSeek(FFileHandle,0,2)
      else                 //无新增内容
        FileSeek(FFileHandle,FFileHead.IndexPos,0);
      //设置数据头
      with FIndexHead do
      begin
        Key:=GetTickCount;
        Size:=Msh.Size;
        Count:=Msd.Size div (sizeof(longint)*2);
      end;
      //加密标题内容
      Encypher(FIndexHead.Key,Msh.Memory^,Msh.Size div 4);
      //写入索引
      FileWrite(FFileHandle,FIndexHead,sizeof(TIndexHead));
      FileWrite(FFileHandle,Msh.Memory^,Msh.Size);
      FileWrite(FFileHandle,Msd.Memory^,Msd.Size);
    end;

    procedure TSrmObject.ReadItemHead(Ps:longint);
    begin
      FActivePos:=Ps;  //保存当前数据位置
      //读出并解密
      with FDataHead do
      begin
        FileSeek(FFileHandle,Ps,0);
        FileRead(FFileHandle,FDataHead,sizeof(TDataHead));
        Decypher(Key,SearchKey,13);
        Decypher(Key,Author,4);
        Decypher(Key,Password,3);
      end;
    end;

    procedure TSrmObject.ReadItemData(DataStream:TMemoryStream);
    var
      size:longint;
    begin
      //读出具体内容
      FileRead(FFileHandle,size,sizeof(longint));
      DataStream.SetSize(size);
      FileRead(FFileHandle,DataStream.Memory^,size);
      Decypher(FDataHead.Key,DataStream.Memory^,size div 4);
    end;

    procedure TSrmObject.EditItemHead(Ps:longint);
    begin
      //修改数据头
      FileSeek(FFileHandle,Ps,0);
      with FDataHead do
      begin
        Encypher(Key,SearchKey,13);
        Encypher(Key,Author,4);
        Encypher(Key,Password,3);
        FileWrite(FFileHandle,FDataHead,sizeof(TDataHead));
        Decypher(Key,SearchKey,13);
        Decypher(Key,Author,4);
        Decypher(Key,Password,3);
      end;
    end;

    function TSrmObject.AddItemHead:longint;
    begin
      //新内容增加时移到文件尾添加
      FChangeFlag:=true;
      with FDataHead do
      begin
        Result:=FileSeek(FFileHandle,0,2);
        Key:=GetTickCount;
        PubDate:=Now;
        Encypher(Key,SearchKey,13);
        Encypher(Key,Author,4);
        Encypher(Key,Password,3);
        FileWrite(FFileHandle,FDataHead,sizeof(TDataHead));
        Decypher(Key,SearchKey,13);
        Decypher(Key,Author,4);
        Decypher(Key,Password,3);
      end;
    end;

    procedure TSrmObject.AddItemData(DataStream:TMemoryStream);
    var
      size:longint;
    begin
      size:=DataStream.Size;
      FileWrite(FFileHandle,size,sizeof(longint));
      Encypher(FDataHead.Key,DataStream.Memory^,size div 4);
      FileWrite(FFileHandle,DataStream.Memory^,size);
    end;

    function TSrmObject.GetItemPassword(Ps:longint):string; //得某标题口令
    var
      Dh:TDataHead;
    begin
      //读出并解密
      with Dh do
      begin
        FileSeek(FFileHandle,Ps,0);
        FileRead(FFileHandle,Dh,sizeof(TDataHead));
        Decypher(Key,Password,3);
      end;
      result:=string(Dh.Password);
    end;

    procedure TSrmObject.SetDbChanged(Value:boolean);
    begin
      FDbChanged:=Value;
    end;

    procedure TSrmObject.SetIndexChanged(Value:boolean);
    begin
      FIndexChanged:=Value;
      if Value then FDbChanged:=Value;
    end;

    procedure TSrmObject.SetItemHeadChanged(Value:boolean);
    begin
      FItemHeadChanged:=Value;
      if Value then
      begin
        FIndexChanged:=Value;
        FDbChanged:=Value;
      end;
    end;

    procedure TSrmObject.SetItemDataChanged(Value:boolean);
    begin
      FItemDataChanged:=Value;
      if Value then
      begin
        FIndexChanged:=Value;
        FDbChanged:=Value;
      end;
    end;

    end.

  • 相关阅读:
    Windows内存布局 / MmPfnDataBase页帧数据库
    保护模式中的PDE与PTE
    保护模式101012分页机制
    Windows系统调用中的系统服务表描述符(SSDT)
    Windows系统调用中的系统服务表
    三环进入零环的细节(KiFastCallEntry函数分析)
    Windows系统调用中API从3环到0环(下)
    SQL反模式学习笔记5 外键约束【不用钥匙的入口】
    SQL反模式学习笔记3 单纯的树
    SQL反模式学习笔记2 乱穿马路
  • 原文地址:https://www.cnblogs.com/zhuor/p/370989.html
Copyright © 2020-2023  润新知