Einzelnen Beitrag anzeigen

Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.453 Beiträge
 
Delphi 12 Athens
 
#27

AW: Schnelle Methode, um eine Dateiliste zu erstellen

  Alt 24. Feb 2021, 14:59
Bei dem Exclude-Fall müsste man unterscheiden, ob lediglich ein Verzeichnis angegeben ist oder ein Verzeichnis mit Wildcards. Im ersten Fall kann man das Verzeichnis überspringen (das macht mein erster Vorschlag), aber im zweiten Fall muss das Verzeichnis gescannt und die entsprechenden Einträge ausgefiltert werden.

Um das besser kontrollieren zu können, würde ich die LstExclude in zwei Listen LstExcludeDirs und LstExcludeFiles aufsplitten. Hier nochmal ein etwas komplexerer Ansatz (mit kleiner Optimierung beim Checken der Excludes) - ungetestet:
Delphi-Quellcode:
procedure ListFiles(const Root: string; LstInclude, LstExclude, Target: TStrings);

  function Matches(const Value: String; const Arr: TArray<string>): Boolean;
  var
    foundIndex: Integer;
  begin
    Result := TArray.BinarySearch<string>(Arr, Value, foundIndex, TIStringComparer.Ordinal);
    if not Result and (foundIndex > 0) then
      Result := Value.StartsWith(Arr[foundIndex-1], True);
  end;

var
  arr: TArray<string>;
  lstExcludeDirs: TStringList;
  lstExcludeFiles: TStringList;
  mask: string;
  path: string;
  S: string;
begin
  if (LstInclude <> nil) and (LstInclude.Count > 0) then begin { Includes vorhanden? }
    for S in LstInclude do begin
      path := TPath.Combine(Root, S);
      mask := '*.*';
      if path.Contains('*') or path.Contains('?') then begin
        mask := TPath.GetFileName(path);
        path := TPath.GetDirectoryName(path);
      end;
      Target.AddStrings(TDirectory.GetFiles(path, mask, TSearchOption.soAllDirectories));
    end;
  end
  else if (LstExclude <> nil) and (LstExclude.Count > 0) then begin { Excludes vorhanden? }
    lstExcludeDirs := TStringList.Create;
    try
      lstExcludeFiles := TStringList.Create;
      try
        for S in LstExclude do begin
          path := S;
          if path.Contains('*') or path.Contains('?') then begin
            LstExcludeFiles.Add(path);
            { damit der Pfad erstmal excluded wird, tragen wir ihn auch in die andere Liste ein }
            path := TPath.GetDirectoryName(path);
          end;
          LstExcludeDirs.Add(path);
        end;

        { Erst arbeiten wir die ganzen Pfade ab und überspringen die Excluded Pfade }
        { Für bessere Performance sortieren wir die Excludes einmal, damit wir in Matches das BinarySearch verwenden können }
        arr := LstExcludeDirs.ToStringArray;
        TArray.Sort<string>(arr, TIStringComparer.Ordinal);

        for path in TDirectory.GetDirectories(Root, '*', TSearchOption.soAllDirectories) do begin
          { ist es ein Exclude Path? }
          if not Matches(path, arr) then
            Target.AddStrings(TDirectory.GetFiles(path, '*.*', TSearchOption.soTopDirectoryOnly));
        end;

        { nun noch die excluded Paths mit den Wildcard-Einträgen }
        for S in lstExcludeFiles do begin
          mask := TPath.GetFileName(S);
          path := TPath.GetDirectoryName(S);
          Target.AddStrings(TDirectory.GetFiles(path, '*.*', TSearchOption.soAllDirectories,
            function(const Path: string; const SearchRec: TSearchRec): Boolean
            begin
              Result := TPath.MatchesPattern(SearchRec.Name, mask, False);
            end
            ));
        end;
      finally
        lstExcludeFiles.Free;
      end;
    finally
      lstExcludeDirs.Free;
    end;
  end
  else begin { keine Einschränkungen }
    Target.AddStrings(TDirectory.GetFiles(Root, '*.*', TSearchOption.soAllDirectories));
  end;
end;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat