Главная страницаОбратная связьКарта сайта

Как получить список файлов и поддиректорий в указанной директории

Автор: Андрей Сорокин
WEB-сайт: http://anso.da.ru

Для использования этого объекта необходима библиотека TRegExpr


{$B-}
unit DirScan;

interface

uses
  RegExpr, SysUtils, Classes;

type
  PDirectoryScannerItem = ^TDirectoryScannerItem;
  TDirectoryScannerItem = packed record
    name : string;
    Size : integer;
    LastWriteTime : TDateTime;
  end;

  TOnDirScanFileProceed = procedure (Sender : TObject; const ABaseFolder : string;
    const ASearchRecord : TSearchRec; var ACancel : boolean) of object;
  TOnDirScanStartFolderScanning = procedure (Sender : TObject; const AFolder : string) of object;
  TOnDirScanTimeSlice = procedure (Sender : TObject; var ACancel : boolean) of object;

  TCustomDirectoryScanner = class
    private
      fRegExprMask : string;
      fRecursive : boolean;
      fCount : integer;
      fOnFileProceed : TOnDirScanFileProceed;
      fOnStartFolderScanning : TOnDirScanStartFolderScanning;
      fOnTimeSlice : TOnDirScanTimeSlice;
      fMaskRegExpr : TRegExpr;
      function BuildFileListInt (const AFolder : string) : boolean;
    public
      constructor Create;
      destructor Destroy; override;

      property Recursive : boolean read fRecursive write fRecursive;
      property RegExprMask : string read fRegExprMask write fRegExprMask;
      // regular expresion for file names masks (like "(\.html?|\.xml)" etc)
      function BuildFileList (AFolder : string) : boolean;
      // Build list of all files in folder AFolder.
      // If ASubFolder = true then recursivly scans subfolders.
      // Returns false if there was file error and user
      // decided to terminate process.

      property Count : integer read fCount;
      // matched in last BuildFileList files count

      // Events
      property OnFileProceed : TOnDirScanFileProceed read fOnFileProceed write fOnFileProceed;
      // for each file matched
      property OnStartFolderScanning : TOnDirScanStartFolderScanning read fOnStartFolderScanning 
        write fOnStartFolderScanning;
      // before scanning each directory (starting with root)
      property OnTimeSlice : TOnDirScanTimeSlice read fOnTimeSlice write fOnTimeSlice;
      // for progress bur an so on (called in each internal iteration)
  end;

  TDirectoryScanner = class (TCustomDirectoryScanner)
   // simple descendant - after BuildFileList call make list of files
   // (You can access list thru Item property)
   private
     fList : TList;
     function GetItem (AIdx : integer) : PDirectoryScannerItem;
     procedure KillItem (AIdx : integer);
     procedure FileProceeding (Sender : TObject; const ABaseFolder : string;
       const ASearchRecord : TSearchRec; var ACancel : boolean);
     procedure TimeSlice (Sender : TObject; var ACancel : boolean);
   public
     constructor Create;
     destructor Destroy; override;

     property Item [AIdx : integer] : PDirectoryScannerItem read GetItem;
  end;



implementation

uses
  Windows, Controls, TFUS;

constructor TCustomDirectoryScanner.Create;
begin
  inherited;
  fRecursive := true;
  fOnFileProceed := nil;
  fOnStartFolderScanning := nil;
  fOnTimeSlice := nil;
  fMaskRegExpr := nil;
  fRegExprMask := "";
end; { of constructor TDirectoryScanner.Create}

destructor TCustomDirectoryScanner.Destroy;
begin
  fMaskRegExpr.Free;
  inherited;
end; { of destructor TCustomDirectoryScanner.Destroy}

function TCustomDirectoryScanner.BuildFileList (AFolder : string) : boolean;
begin
  if (length (AFolder) > 0) and (AFolder [length (AFolder)] = "\")
   then AFolder := copy (AFolder, 1, length (AFolder) - 1);

  fMaskRegExpr := TRegExpr.Create;
  fMaskRegExpr.Expression := RegExprMask;

  fCount := 0;
  Result := BuildFileListInt (AFolder);
end; { function BuildFileList}

function TCustomDirectoryScanner.BuildFileListInt (const AFolder : string) : boolean;
var
  sr : SysUtils.TSearchRec;
  Canceled : boolean;
begin
  Result := true;
  if Assigned (OnStartFolderScanning)
   then OnStartFolderScanning (Self, AFolder + "\");

  if SysUtils.FindFirst (AFolder + "\" + "*.*", faAnyFile, sr) = 0 then try
       repeat
        try
           if (sr.Attr and SysUtils.faDirectory) = SysUtils.faDirectory then begin
             if Recursive and (sr.name <> ".") and (sr.name <> "..")
              then Result := BuildFileListInt (AFolder + "\" + sr.name);
             end
            else begin
               if fMaskRegExpr.Exec (sr.name) then begin
                Canceled := false;
                if Assigned (OnFileProceed)
                 then OnFileProceed (Self, AFolder, sr, Canceled);
                if Canceled
                 then Result := false;
                inc (fCount);
               end;
             end;
          except on E:Exception do begin
            case MsgBox ("Replacing error",
                  "Can""t replace file contetn due to error:"#$d#$a#$d#$a
                  + E.message + #$d#$a#$d#$a + "Continue processing ?",
                  mb_YesNo or mb_IconQuestion) of
              mrYes : Result := false;
              >else ; // must be No
             end;
           end;
         end;
        Canceled := false;
        if Assigned (OnTimeSlice)
         then OnTimeSlice (Self, Canceled);
        if Canceled
         then Result := false;
       until not Result or (SysUtils.FindNext (sr) <> 0);
      finally SysUtils.FindClose (sr);
     end;
  if not Result
   then EXIT;
end; { function BuildFileListInt}

constructor TDirectoryScanner.Create;
begin
  inherited;
  fList := TList.Create;
  OnFileProceed := FileProceeding;
  fOnTimeSlice := TimeSlice;
end; { of constructor TDirectoryScanner.Create}

destructor TDirectoryScanner.Destroy;
var
  i : integer;
begin
  for i := fList.Count - 1 downto 0 do
   KillItem (i);
  fList.Free;
  inherited;
end; { of destructor TDirectoryScanner.Destroy}

procedure TDirectoryScanner.KillItem (AIdx : integer);
var
  p : PDirectoryScannerItem;
begin
  p := PDirectoryScannerItem (fList.Items [AIdx]);
  Dispose (p);
  fList.Delete (AIdx);
end; { of procedure TDirectoryScanner.KillItem}

function TDirectoryScanner.GetItem (AIdx : integer) : PDirectoryScannerItem;
begin
  Result := PDirectoryScannerItem (fList.Items [AIdx]);
end; { of function TDirectoryScanner.GetItem}

procedure TDirectoryScanner.FileProceeding (Sender : TObject; const ABaseFolder : string;
const ASearchRecord : TSearchRec; var ACancel : boolean);
var
  p : PDirectoryScannerItem;
begin
  p := New (PDirectoryScannerItem);
  p.name := ABaseFolder + "\" + ASearchRecord.name;
  fList.Add (p);
end; { of procedure TDirectoryScanner.FileProceeding}

procedure TDirectoryScanner.TimeSlice (Sender : TObject; var ACancel : boolean);
begin
  if Count mod 100 = 0
   then Sleep (0);
end; { of procedure TDirectoryScanner.TimeSlice}

end.


Обсудить статью на форуме


Если Вас заинтересовала или понравилась информация по разработке на Delph - "Как получить список файлов и поддиректорий в указанной директории", Вы можете поставить закладку в социальной сети или в своём блоге на данную страницу:

Так же Вы можете задать вопрос по работе этого модуля или примера через форму обратной связи, в сообщение обязательно указывайте название или ссылку на статью!
   


Copyright © 2008 - 2024 Дискета.info