Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Alle Filenamen (https://www.delphipraxis.net/215094-alle-filenamen.html)

himitsu 9. Mai 2024 13:43

AW: Alle Filenamen
 
Zitat:

Suchmaschine Deiner Wahl
oder hier im Haus
FindFirstFindFirst
Dateien suchenDateien suchen

Hier im Forum suchenFindFirst
Hier im Forum suchenDateien suchen

wendelin 9. Mai 2024 15:38

AW: Alle Filenamen
 
Hallo,
nochmals Danke an Alle.

Ich werde die verschiedenen Vorschläge ausprobieren.

Wolfgang (Wendelin)

wendelin 14. Mai 2024 16:14

AW: Alle Filenamen
 
Hallo Delphi-freunde

Nochmals vielen dank für Eure zahlreichen Antworten.
Nicht Alles funktionierte.
Mein Dank an TurboMagic und PapaSchlumpf.
Ihr Vorschlag funktionierte am besten.

Delphi-Quellcode:
procedure TForm1.GetFileListEx(const Directory: string;Myfiles :TStrings;const FileMask: string);
var SearchRec: TSearchRec;
    lauf    : Integer;
begin
  // Application.ProcessMessages; <-- habe ich drauf verzichtet
  Pfad_und_Header;  // von mir eingesetzt
  lauf   := 0;
  if FindFirst(IncludeTrailingPathDelimiter(Directory)+ FileMask, faAnyFile and not faDirectory
  and not faVolumeID and not faHidden, SearchRec) = 0 then
  try
    repeat
   //  MyFiles.Add(IncludeTrailingPathDelimiter(directory)+SearchRec.Name);
   // habe ich herausgenommen da Fehlermeldung !!
    INC(lauf);
    StringGrid1.Cells[0,lauf] := (IncludeTrailingPathDelimiter(directory)+SearchRec.Name);
    until FindNext(SearchRec) <> 0;
  finally SysUtils.FindClose(SearchRec);
  end;
  glb_Lauf := lauf;
end;

procedure TForm1.SpeedButton4Click(Sender: TObject);
Var Directory : String;
    MyFiles  : TStrings;
    FileMask : String;
begin
  Directory := 'F:\d_Mat2';
  FileMask := '*.*';
  GetFileListEx(Directory,MyFiles,FileMask);
end;
Alles läuft prima.

Jetzt habe ich aber noch 2 Fragen.
1. wo ist der Fehler in meinem noch kürzeren Code.?

Delphi-Quellcode:
procedure TForm1.SpeedButton3Click(Sender: TObject);
Var Path      : String;
    F         : TSearchRec;
    FileAttr  : integer;
    Mask      : String;
    zaehler   : Integer;
begin
  FileAttr := faAnyFile;
  zaehler := 0;
  Path    := 'F:\d_Mat2';
  Mask    := '*.*';
  If FindFirst(Path + Mask,FileAttr,F) = 0 then try
    repeat
      INC(Zaehler);
      StringGrid1.Cells[0,zaehler] := F.Name; // die Schleife wird nur einmal
                                               // durchlaufen . Ergebnis : Nur der Pfad --> F:\d_Mat2
    until FindNext(F) <> 0;
  finally
    FindClose(F);
  end;
end;
2. Frage :
Wenn ich das StringGrid durchlaufe, muss ich mit der API- Function "ShellExecute" arbeiten um jeden einzelnen File abzuarbeiten,
oder kann ich das auch anders lösen ?

Delphi-Quellcode:
procedure TForm1.BitBtn1Click(Sender: TObject);
Var i      : Integer;
    MyStock : String;
    MyPath : String;
begin
  For i := 1 to glb_Lauf do
  begin
    MyPath := StringGrid1.Cells[0,i];
  //  ShellExecute(0,MyPath,'OPEN',0,0,Nil);  
  end;
end;

Papaschlumpf73 14. Mai 2024 16:28

AW: Alle Filenamen
 
Zu Frage 1: Zwischen Path und Mask fehlt der Backslash (weil du IncludeTrailingPathDelimiter entfernt hast).

KodeZwerg 14. Mai 2024 16:40

AW: Alle Filenamen
 
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.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:04 Uhr.
Seite 2 von 2     12   

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