⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adobackup.pas

📁 数据备份与恢复源码,给需要的一个参考,可以直接运行
💻 PAS
📖 第 1 页 / 共 3 页
字号:
// ************************  ADOBackUP ******************************
//
// 引用外部控件:   BackUp ------ 可实现多个文件压缩成单一文文件
//                  DialogEx ---- 可预览的 Dialog
// 更新功能:
//     2001.3.15
//       包文件的名称定为Save.dat,后面依次为:Save1.dat,Save2.dat ....
//       增加删除数据选项,可自动删除旧数据,也可传递通过传递SQl删除。
//       增加数据包信息,使用户可以随数据包传送文本信息,以便终端识别。
//
//     2001.2.21
//       备份 Backup  : 根据读取的外部Sql语句,备份数据,生成备份文件。
//                       可根据需要,分割备份文件,可直接用A盘存储。
//       恢复 Restore : 选择备份文件,可自动合并在同一目录的文件。
//                       根据条件恢复相关数据。
//       备份、恢复过程有进度提示。
//
//     2001.4.4
//       备份文件格式改变:不再存储 Info.Txt,而是存放于备份文件头
//
// 注意:作为备份依据的字段,如果修改,则可能造成数据重复或不能正确入库
//
//********************************************************************


unit ADOBackUP;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Db, ADODB, FileCtrl, Backup, DialogEx;
type
  TFloppyFileHead = record
    ID: array[0..3] of char; //  文件标志, 正常为 JSFB 四个字符
    SerialNo: Double; //  序列号
    FloppyCount: Smallint; //  磁盘总数
    CurFloppyNo: Smallint; //  当前磁盘号
    FileSize: integer; //  文件大小
    FileName: string[60]; //  原始文件名
    Information: array[0..43] of char; //  附加信息
  end;

  TErrorType = (etCancel, etError);
  TReturnType = (rtAll, rtTable, rtSql);
  TRatioChangedEvent = procedure(Sender: TObject; Ratio: Integer) of object;

  TADOBackUP = class(TComponent)
  private
    { Private declarations }
    FPackSize: Integer; // 每个包文件的大小
    FBackUpFileName: string; // 包文件名
    FTempPath, FSavePath, FWorkPath, FOrigPath: string; // 临时目录
    FSourceFile: string; // 含路径
    FADOConnection: TADOConnection; // 数据库源
    FSQLStrings: TStrings; // Sql语句
    FDelSQLStrings: TStrings; // 传递删除Sql语句
    FInfo: TStrings; // 附带信息
    TableMaps: TStrings; // 文件名映射
    FIsDevide: Boolean; // 是否分割文件
    FIsSavetoA: Boolean;
    FRadio: integer; // 拷贝进度
    FRatioChanged: TRatioChangedEvent;
    FAutoDel: Boolean; // 是否自动删除数据

    FFloppyFileHead: TFloppyFileHead;
    FFileHeadList: array of TFloppyFileHead;
    FErrorType: TErrorType;

    BackupFile: TBackupFile;

    function StartWrong: Boolean;
    function CopyDevide: Boolean; // 拷贝分割文件  
    function CopyFloopyFile: Boolean; //  将文件进行分割
    function MergeFloopyFile: Boolean; // 将文件进行合并

    procedure CalFloppyHeadList; //  计算每包文件头(分割拷贝前准备)
    procedure RemoveDir(DirName: string); // 删除临时单层目录
    function CopyfromAtoTemp: Boolean; // 将文件从A转移至临时目录
    function CopytoTemp(SourcePath: string): Boolean; // 文件转移至临时目录
    function RestoreData: Boolean; // 更新数据库
    function GetTableName(mSql: TStrings; ReturnType: TReturnType = rtAll): TStrings;
    procedure RebackFiles(mfileName: string); // 恢复文件

    procedure SetSqlStrings(Value: TStrings);
    procedure SetDelSQLStrings(Value: TStrings);
    procedure SetInfo(Value: TStrings);
    function GenerateTempName(Path: string): string;
    procedure PreviewFile(Sender: TOpenPreviewDialog; FileName: string);
 //   Function CopyFromSource:Boolean;  // 从备份转移文件
  protected
    { Protected declarations }
  public
    { Public declarations }

    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    function Backup(SavePath: string): Boolean;
    function Restore(SourceFile: string): Boolean;
    function GetInfo(SourceFile: string): Boolean; // 是否合法的备份文件
    function BrowseBackFile: string;

  published
    { Published declarations }
    property AutoDel: Boolean read FAutoDel write FAutoDel default True;
    property Info: TStrings read FInfo write SetInfo;
    property PackSize: Integer read FPackSize write FPackSize default 1456000;
    property BackUpFileName: string read FBackUpFileName write FBackUpFileName;
    property ADOConnection: TADOConnection read FADOConnection write FADOConnection;
    property SQLStrings: TStrings read FSQLStrings write SetSqlStrings;
    property DelSQLStrings: TStrings read FDelSQLStrings write SetDelSQLStrings;
    property IsDevide: Boolean read FIsDevide write FIsDevide;
    property Procession: TRatioChangedEvent read FRatioChanged write FRatioChanged;
  end;

procedure Register;

implementation

const
  fn_TableMap = '_TblMap.txt';
  fn_SQLFile = '_SQL.Txt';
  BackupSign = #$AA#$55#0'SWAT';

procedure Register;
begin
  RegisterComponents('FVCL', [TADOBackUP]);
end;

procedure TADOBackUp.SetSqlStrings(Value: TStrings);
begin
  if Assigned(Value) then
    FSqlStrings.Assign(Value);
end;

procedure TADOBackUp.SetDelSQLStrings(Value: TStrings);
begin
  if Assigned(Value) then
    FDelSqlStrings.Assign(Value);
end;

procedure TADOBackup.SetInfo(Value: TStrings);
begin
  if Assigned(Value) then
    FInfo.Assign(Value);
end;

// 在指定路径(Path)下生成唯一的临时文件名

function TADOBackup.GenerateTempName(Path: string): string;
  function IntToBase32(Number: Longint): string;
  const
    Table: array[0..31] of Char = '0123456789ABCDEFGHIJKLMNOPQRSTUV';
  var
    I: Integer;
  begin
    Result := '';
    for I := 0 to 4 do
    begin
      Insert(Table[Number and 31], Result, 1);
      Number := Number shr 5;
    end;
  end;
var
  Rand, RandOrig: Longint;
begin
  RandOrig := Random($2000000);
  Rand := RandOrig;
  repeat
    Inc(Rand);
    if Rand > $1FFFFFF then Rand := 0;
    if Rand = RandOrig then
      raise Exception.Create('建立临时文件失败');
    Result := 'Dat' + IntToBase32(Rand);
  until not FileExists(Path + Result);
end;

function TADOBackup.GetInfo(SourceFile: string): Boolean; // 是否合法的备份文件
var
  mReadFile: file of Byte;
  InfoLen: Integer;
  InfoText: string;
begin
  Assignfile(mReadFile, SourceFile);
  InfoText := '';
  Result := False;
  try
    try
      ReSet(mReadFile);
      if not Eof(mReadFile) then
        BlockRead(mReadFile, FFloppyFileHead, Sizeof(TFloppyFileHead));
      if FFloppyFileHead.ID <> 'JSFB' then // 表明不是经过处理后的包文件
        ReSet(mReadFile);
      SetLength(InfoText, Length(BackUpSign));
      BlockRead(mReadFile, InfoText[1], Length(BackUpSign));
      if InfoText = BackUpSign then
      begin
        Result := True;
        BlockRead(mReadFile, InfoLen, Sizeof(Integer));
        SetLength(InfoText, InfoLen);
        BlockRead(mReadFile, InfoText[1], InfoLen);
      end;
    finally
      CloseFile(mReadFile);
    end;
  except
  end;
  FInfo.Text := InfoText;
end;

function TADOBackup.GetTableName(mSql: TStrings; ReturnType: TReturnType = rtAll): TStrings;
  function PosStr(substr: string; s: string): Integer; //
  begin
    s := stringReplace(s, substr, '^', [rfIgnoreCase]);
    Result := Pos('^', s);
  end;
var
  i: integer;
  Sqltxt: string;
  posint: integer;
  mtableName, mtablesql: string;
begin
  Result := Tstringlist.Create;
  for i := 0 to mSql.Count - 1 do
  begin
    Sqltxt := mSql[i];
    posint := posstr('from', Sqltxt);
    if posint <> 0 then
    begin
      delete(sqltxt, 1, posint + 4); // 删去空格
      mtableName := copy(Sqltxt, 1, pos(' ', Sqltxt) - 1);
      posint := posstr('Where', Sqltxt);
      mtablesql := '';
      if posint = 0 then
        mtableName := SqlTxt
      else
      begin
        delete(sqltxt, 1, posint + 5);
        mtablesql := 'Where ' + Copy(Sqltxt, 1, length(Sqltxt));
      end;

      case ReturnType of
        rtAll:
          begin
            if posint <> 0 then
              mtablesql := ',' + mtablesql;
            Result.Add(mtableName + mtablesql);
          end;
        rtTable:
          Result.Add(mtableName);
        rtSql:
          Result.Add(mtablesql);
      end;
    end;
  end;
end;

function TADOBackup.MergeFloopyFile: Boolean;
var
  SFile: string;
  tmpS: string;
  ErrorFlag: Boolean;
  SHandle, THandle: Integer;
  i, j: integer;
  BlockCount, LastBlockSize: integer;
  Buffers: array[0..4095] of char;
  Excursion: Integer;
  TempFileName: string;
begin
  Result := True;
  ErrorFlag := False;
  TempFileName := FOrigPath + FBackUpFileName;

  THandle := FileCreate(TempFileName);

  SHandle := -1;

  SFile := StringReplace(FBackUpFileName, '.', InttoStr(1) + '.', [rfReplaceAll, rfIgnoreCase]);
  SFile := fTempPath + SFile;

  for i := 0 to Length(FFileHeadList) - 1 do
  begin
    TempFileName := ExtractFileName(SFile);
    Excursion := Length(inttostr(i + 1)) + 1; // 计算.偏移位数
    if i = 0 then
      SFile := ExtractFilePath(SFile) + Copy(TempFileName, 1, pos('.', TempFileName) - Excursion)
        + ExtractFileExt(SFile)
    else if i = 1 then
      SFile := ExtractFilePath(SFile) + Copy(TempFileName, 1, pos('.', TempFileName) - 1)
        + Inttostr(i + 1) + ExtractFileExt(SFile)
    else
      SFile := ExtractFilePath(SFile) + Copy(TempFileName, 1, pos('.', TempFileName) - Excursion)
        + Inttostr(i + 1) + ExtractFileExt(SFile);
    if FileExists(SFile) then
    begin
      SHandle := FileOpen(SFile, fmOpenRead or fmShareDenyNone);
      if SHandle = -1 then
      begin
        tmpS := '读备份数据 ' + IntToStr(i + 1) + ' 号盘错误, ';
        ErrorFlag := True;
        Break;
      end;
    end
    else
    begin
      tmpS := '没有发现备份数据 ' + IntToStr(i + 1) + ' 号盘, ';
      ErrorFlag := True;
      Break;
    end;

    // 设置读写缓冲区大小
    BlockCount := (FFileHeadList[i].FileSize - Sizeof(TFloppyFileHead)) div 4096;
    LastBlockSize := (FFileHeadList[i].FileSize - Sizeof(TFloppyFileHead)) mod 4096;

    FileSeek(SHandle, Sizeof(TFloppyFileHead), 0);
    for j := 1 to BlockCount do
    begin
      FileRead(SHandle, Buffers, 4096);
      FileWrite(THandle, Buffers, 4096);
    end;
    if LastBlockSize > 0 then
    begin
      FileRead(SHandle, Buffers, LastBlockSize);
      FileWrite(THandle, Buffers, LastBlockSize);
    end;
    FileClose(SHandle);
    DeleteFile(SFile);
  end;
  FileClose(THandle);

  if ErrorFlag then
    Result := False;
end;

procedure TADOBackup.RemoveDir(DirName: string);
var
  FSearchRec: TSearchRec;
  FindResult: integer;
begin
  try
    FindResult := FindFirst(DirName + '*.*', faAnyFile + faHidden + faSysFile, FSearchRec);
    try
      while FindResult = 0 do
      begin
        Deletefile(DirName + FSearchRec.Name);
        FindResult := FindNext(FSearchRec);
      end;
    finally
      FindClose(FSearChRec);
    end;
    rmDir(DirName);
  except
  end;
end;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -