AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Alle Filenamen

Ein Thema von wendelin · begonnen am 7. Mai 2024 · letzter Beitrag vom 14. Mai 2024
 
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#15

AW: Alle Filenamen

  Alt 14. Mai 2024, 16:40
Falls sich die Anforderungen mal steigern und Du mehr Geschwindigkeit bei der Dateisuche brauchst, das hier habe ich mir mal gebastelt:
Ich kann unter keinen Umständen empfehlen die 2 sub-routinen zu ändern aber der wrapper "FindEx" kann natürlich beliebig umgeschrieben und angepasst werden.
Ein paar Erklärungen sind in Englisch enthalten.
Delphi-Quellcode:
unit uFindEx;

interface

uses
  Winapi.Windows,
  System.SysUtils;

type
  // My variant of an "StringList"
  TFindArray = TArray<string>; // array of WideString;

function FindEx(const ABasePath: string; const AFoldersMustExist: string = ''; AExludedFolders: string = ''; const AFileMask: string = '*.*'; const AIncludeSubFolders: Boolean = False): TFindArray;

implementation

const
  // missing FindEx flags
  FIND_FIRST_EX_CASE_SENSITIVE = $00000001;
  FIND_FIRST_EX_LARGE_FETCH = $00000002;
  FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY = $00000004;

// Small helper to add strings in my "StringList"
procedure AddFindArray(var AFindArray: TFindArray; const AString: string); inline;
var
  i: Integer;
begin
  i := Length(AFindArray);
  SetLength(AFindArray, Succ(i));
  AFindArray[i] := AString;
end;

// This method will crawl thru a folder and collect their names
// The ExclusionList should contain full path names that be total excluded from search, by default everything is included
// IncludeSubFolders switch will get every folder, False by default
// Based upon very fast FindEx Api (Windows)
// The result will contain full path
function FindExFolders(const ABasePath: string = ''; const AExclusionList: TFindArray = []; const AIncludeSubFolders: Boolean = False): TFindArray;
var
  FindExHandle : THandle;
  Win32FindData : TWin32FindDataW;
  FindExInfoLevels: TFindexInfoLevels;
  FindExSearchOps : TFindexSearchOps;
  AdditionalFlags : DWORD;
  tmp : TFindArray;
  i, ii : Integer;
  s:string;
begin
  SetLength(Result, 0);
  if ((ABasePath = '') or (not DirectoryExists(ABasePath))) then
    Exit;
  FindExInfoLevels := FindExInfoBasic;
  FindExSearchOps := FindExSearchLimitToDirectories;
  AdditionalFlags := FIND_FIRST_EX_LARGE_FETCH or FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY;
  FindExHandle := Winapi.Windows.FindFirstFileExW(
                        PWideChar(IncludeTrailingBackslash(ABasePath) + '*.*')
                        ,FindExInfoLevels, @Win32FindData, FindExSearchOps, nil
                        ,AdditionalFlags);
  if (FindExHandle <> INVALID_HANDLE_VALUE) then
    begin
      repeat
        if ((Win32FindData.cFileName <> string('.')) and (Win32FindData.cFileName <> string('..'))
            and (0 <> (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY))) then
          begin
            if (Length(AExclusionList) > 0) then
              begin
                for i := Low(AExclusionList) to High(AExclusionList) do
                  if (0 = Pos(UpperCase(AExclusionList[i]), UpperCase(IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName))) then
                    AddFindArray(Result, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName);
              end
              else
                AddFindArray(Result, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName);
          end;
      until (not Winapi.Windows.FindNextFileW(FindExHandle, Win32FindData));
      Winapi.Windows.FindClose(FindExHandle);
    end;
  if AIncludeSubFolders then
    for i := Low(Result) to High(Result) do
      begin
        tmp := FindExFolders(Result[i], AExclusionList, AIncludeSubFolders);
        for ii := Low(tmp) to High(tmp) do
          AddFindArray(Result, tmp[ii]);
      end;
  SetLength(tmp, 0);
end;

// This method will crawl thru a folder and collect their filenames
// IncludeSubFolders switch will get every filename, False by default
// Based upon very fast FindEx Api (Windows)
// The result will contain full path + filename
function FindExFiles(const ABasePath: string = ''; const AFileMask: string = '*.*'; const AIncludeSubFolders: Boolean = False): TFindArray;
var
  FindExHandle : THandle;
  Win32FindData : TWin32FindDataW;
  FindExInfoLevels: TFindexInfoLevels;
  FindExSearchOps : TFindexSearchOps;
  AdditionalFlags : DWORD;
  tmp, Folders : TFindArray;
  i, ii : Integer;
begin
  SetLength(Result, 0);
  if ((ABasePath = '') or (not DirectoryExists(ABasePath))) then
    Exit;
  SetLength(Folders, 0);
  SetLength(tmp, 0);
  FindExInfoLevels := FindExInfoBasic;
  FindExSearchOps := FindExSearchLimitToDirectories;
  AdditionalFlags := FIND_FIRST_EX_LARGE_FETCH or FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY;
  FindExHandle := Winapi.Windows.FindFirstFileExW(
                        PWideChar(IncludeTrailingBackslash(ABasePath) + AFileMask)
                        ,FindExInfoLevels, @Win32FindData, FindExSearchOps, nil
                        ,AdditionalFlags);
  if (FindExHandle <> INVALID_HANDLE_VALUE) then
    begin
      repeat
        if ((Win32FindData.cFileName <> string('.')) and (Win32FindData.cFileName <> string('..'))) then
          begin
            if (0 = (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)) then
              AddFindArray(Result, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName);
            if (AIncludeSubFolders and
               (0 <> (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY))) then
              AddFindArray(Folders, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName);
          end;
      until (not Winapi.Windows.FindNextFileW(FindExHandle, Win32FindData));
      Winapi.Windows.FindClose(FindExHandle);
    end;
  if AIncludeSubFolders then
    for i := Low(Folders) to High(Folders) do
      begin
        tmp := FindExFiles(Folders[i], AFileMask, AIncludeSubFolders);
        for ii := Low(tmp) to High(tmp) do
          AddFindArray(Result, tmp[ii]);
      end;
  SetLength(Folders, 0);
  SetLength(tmp, 0);
end;

// My variant of how a file search method can be done for windows systems
// BasePath = where do we start at? eg "C:\Users"
// FoldersMustExist = what foldername is a must for results? eg "Documents", can be left empty for all (seperate with ";" if more than 1)
// ExludedFolders = in what foldername you do not want to search? eg "Documents", can be left empty for all (seperate with ";" if more than 1)
// FileMask = what files you hunt for? eg "*.pas"
// IncludeSubFolders = yes or no, you choose. False by default
// based upon my "FindExFolders" and "FindExFiles" methods
function FindEx(const ABasePath: string; const AFoldersMustExist: string = ''; AExludedFolders: string = ''; const AFileMask: string = '*.*'; const AIncludeSubFolders: Boolean = False): TFindArray;
var
 tmp, Folders, Files: TFindArray;
 splitIncluded, splitExcluded: TFindArray;
 i, ii: Integer;
begin
  SetLength(Result, 0);
  SetLength(tmp, 0);
  SetLength(Folders, 0);
  SetLength(Files, 0);
  SetLength(splitIncluded, 0);
  SetLength(splitExcluded, 0);

  // prepare splittings
  if (Length(AFoldersMustExist) > 0) then
    begin
      if (0 <> Pos(';', AFoldersMustExist)) then
        splitIncluded := AFoldersMustExist.Split([';'])
      else
        AddFindArray(splitIncluded, AFoldersMustExist);
    end;
  if (Length(AExludedFolders) > 0) then
    begin
      if (0 <> Pos(';', AExludedFolders)) then
        splitExcluded := AExludedFolders.Split([';'])
      else
        AddFindArray(splitExcluded, AExludedFolders);
    end;

  // collect folder(s) to work on
  if AIncludeSubFolders then
    tmp := FindExFolders(ABasePath, splitExcluded, AIncludeSubFolders)
    else
    AddFindArray(tmp, ABasePath);

  // sieve out folders that match criteria
  if (Length(splitIncluded) > 0) then
    begin
      for i := Low(tmp) to High(tmp) do
        for ii := Low(splitIncluded) to High(splitIncluded) do
          if (0 <> Pos(UpperCase(splitIncluded[ii]), UpperCase(tmp[i]))) then
            AddFindArray(Folders, tmp[i]);
    end
    else
      Folders := tmp;

  // get files that matching the criteria
  for i := Low(Folders) to High(Folders) do
    begin
      if (Length(AFileMask) > 0) then
        tmp := FindExFiles(Folders[i], AFileMask) // do not enable the IncludeSubFolders switch here (!)
      else
        tmp := FindExFiles(Folders[i]);
      for ii := Low(tmp) to High(tmp) do
        AddFindArray(Files, tmp[ii]);
    end;

  Result := Files;
  SetLength(tmp, 0);
  SetLength(Folders, 0);
  SetLength(Files, 0);
  SetLength(splitIncluded, 0);
  SetLength(splitExcluded, 0);
end;

end.
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:21 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz