在 Delphi 中列出一个巨大目录中的所有 exe 文件的最快方法是什么?
What's the fastest way to list all the exe files in a huge directory in Delphi?
目前我正在做这样的事情:
var
Files: TArray<String>;
if IncludeSubDirs then
Files := TDirectory.GetFiles(Path, '*.exe', TSearchOption.soAllDirectories)
else
Files := TDirectory.GetFiles(Path, '*.exe', TSearchOption.soTopDirectoryOnly);
Path
是用户定义的 String
可以指向任何现有目录。对于包含大量文件和 IncludeSubDirs = True
(例如 C:\Windows\)的“大”目录,GetFiles
需要很长时间(如 30+ 秒)。
用 Delphi(如果有的话)在 Windows 下的“大”目录中列出所有 exe 文件的最快方法是什么?
我做了一些基准测试,对于一个巨大的目录,FindFirst
/ FindNext
比使用 TDirectory
快大约 1.5% 到 3%。我会说两者的速度相当(对于我的用例,我每分钟节省了大约 1 秒)。我最终使用 FindFirst
/ FindNext
因为你会逐渐获得结果而不是一次全部,内存管理似乎更好并且更容易中途取消。我还使用了 TThread
来避免阻塞我的 UI.
这就是我最终得到的结果:
procedure TDirectoryWorkerThread.AddToTarget(const Item: String);
begin
if (not Self.Parameters.DistinctResults) or (Self.Target.IndexOf(Item) = -1) then
Self.Target.Add(Item);
end;
procedure TDirectoryWorkerThread.ListFilesDir(Directory: String);
var
SearchResult: TSearchRec;
begin
Directory := IncludeTrailingPathDelimiter(Directory);
if FindFirst(Directory + '*', faAnyFile, SearchResult) = 0 then
begin
try
repeat
if (SearchResult.Attr and faDirectory) = 0 then
begin
if (Self.Parameters.AllowedExtensions = nil) or (Self.Parameters.AllowedExtensions.IndexOf(ExtractFileExt(SearchResult.Name)) <> -1) then
AddToTarget(Directory + SearchResult.Name);
end
else if Self.Parameters.IncludeSubDirs and (SearchResult.Name <> '.') and (SearchResult.Name <> '..') then
ListFilesDir(Directory + SearchResult.Name);
until Self.Terminated or (FindNext(SearchResult) <> 0);
finally
FindClose(SearchResult);
end;
end;
end;
目前我正在做这样的事情:
var
Files: TArray<String>;
if IncludeSubDirs then
Files := TDirectory.GetFiles(Path, '*.exe', TSearchOption.soAllDirectories)
else
Files := TDirectory.GetFiles(Path, '*.exe', TSearchOption.soTopDirectoryOnly);
Path
是用户定义的 String
可以指向任何现有目录。对于包含大量文件和 IncludeSubDirs = True
(例如 C:\Windows\)的“大”目录,GetFiles
需要很长时间(如 30+ 秒)。
用 Delphi(如果有的话)在 Windows 下的“大”目录中列出所有 exe 文件的最快方法是什么?
我做了一些基准测试,对于一个巨大的目录,FindFirst
/ FindNext
比使用 TDirectory
快大约 1.5% 到 3%。我会说两者的速度相当(对于我的用例,我每分钟节省了大约 1 秒)。我最终使用 FindFirst
/ FindNext
因为你会逐渐获得结果而不是一次全部,内存管理似乎更好并且更容易中途取消。我还使用了 TThread
来避免阻塞我的 UI.
这就是我最终得到的结果:
procedure TDirectoryWorkerThread.AddToTarget(const Item: String);
begin
if (not Self.Parameters.DistinctResults) or (Self.Target.IndexOf(Item) = -1) then
Self.Target.Add(Item);
end;
procedure TDirectoryWorkerThread.ListFilesDir(Directory: String);
var
SearchResult: TSearchRec;
begin
Directory := IncludeTrailingPathDelimiter(Directory);
if FindFirst(Directory + '*', faAnyFile, SearchResult) = 0 then
begin
try
repeat
if (SearchResult.Attr and faDirectory) = 0 then
begin
if (Self.Parameters.AllowedExtensions = nil) or (Self.Parameters.AllowedExtensions.IndexOf(ExtractFileExt(SearchResult.Name)) <> -1) then
AddToTarget(Directory + SearchResult.Name);
end
else if Self.Parameters.IncludeSubDirs and (SearchResult.Name <> '.') and (SearchResult.Name <> '..') then
ListFilesDir(Directory + SearchResult.Name);
until Self.Terminated or (FindNext(SearchResult) <> 0);
finally
FindClose(SearchResult);
end;
end;
end;