Windows 檔案搜尋功能能遍歷所有子目錄,其核心是遞歸遍歷目錄樹。本文展示如何在 Delphi 中使用 FindFirst/FindNext/FindClose API 結合遞歸函數,實現指定根目錄下所有層級子目錄的文件查詢,返回完整路徑列表。
| 函數 | 用途 |
|---|---|
| FindFirst(Path, Attr, SearchRec) | 查找第一個匹配項,返回 0 表示成功 |
| FindNext(SearchRec) | 查找下一個匹配項,返回 0 表示成功 |
| FindClose(SearchRec) | 釋放搜尋句柄資源 |
| FileExists(FileName) | 快速判斷文件是否存在 |
faDirectory,排除 . 和 ..),存入字串列表。子目錄名 + '\')。function IsValidDir(SearchRec: TSearchRec): Boolean;
begin
Result := (SearchRec.Attr = faDirectory) and
(SearchRec.Name <> '.') and
(SearchRec.Name <> '..');
end;
function SearchFile(mainpath, filename: string; var foundresult: TStrings): Boolean;
var
i: Integer;
Found: Boolean;
subdir1: TStrings;
searchRec: TSearchRec;
begin
Found := False;
if Trim(filename) <> '' then begin
subdir1 := TStringList.Create; {必須動態創建,遞歸時每層獨立}
try
{1. 獲取所有子目錄}
if FindFirst(mainpath + '*.*', faDirectory, searchRec) = 0 then begin
if IsValidDir(searchRec) then subdir1.Add(searchRec.Name);
while FindNext(searchRec) = 0 do
if IsValidDir(searchRec) then subdir1.Add(searchRec.Name);
end;
FindClose(searchRec);
{2. 查找當前目錄}
if FileExists(mainpath + filename) then begin
Found := True;
foundresult.Add(mainpath + filename);
end;
{3. 遞歸查詢各子目錄}
for i := 0 to subdir1.Count - 1 do
Found := SearchFile(mainpath + subdir1[i] + '\', filename, foundresult) or Found;
finally
subdir1.Free; {釋放資源}
end;
end;
Result := Found;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
list: TStrings;
begin
list := TStringList.Create;
try
if SearchFile('C:\Downloads\', 'readme.txt', list) then
Memo1.Lines := list
else
ShowMessage('未找到文件');
finally
list.Free;
end;
end;
unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Edit1: TEdit; {輸入文件名}
Edit2: TEdit; {輸入根目錄}
procedure Button1Click(Sender: TObject);
end;
var Form1: TForm1;
implementation
{$R *.dfm}
function IsValidDir(SearchRec: TSearchRec): Boolean;
begin
Result := (SearchRec.Attr = faDirectory) and (SearchRec.Name <> '.') and (SearchRec.Name <> '..');
end;
function SearchFile(mainpath, filename: string; var foundresult: TStrings): Boolean;
var i: Integer; Found: Boolean; subdir1: TStrings; searchRec: TSearchRec;
begin
Found := False;
if Trim(filename) <> '' then begin
subdir1 := TStringList.Create;
try
if FindFirst(mainpath + '*.*', faDirectory, searchRec) = 0 then begin
if IsValidDir(searchRec) then subdir1.Add(searchRec.Name);
while FindNext(searchRec) = 0 do
if IsValidDir(searchRec) then subdir1.Add(searchRec.Name);
end;
FindClose(searchRec);
if FileExists(mainpath + filename) then begin
Found := True; foundresult.Add(mainpath + filename);
end;
for i := 0 to subdir1.Count - 1 do
Found := SearchFile(mainpath + subdir1[i] + '\', filename, foundresult) or Found;
finally subdir1.Free; end;
end;
Result := Found;
end;
procedure TForm1.Button1Click(Sender: TObject);
var list: TStrings;
begin
list := TStringList.Create;
try
if SearchFile(Edit2.Text, Edit1.Text, list) then Memo1.Lines := list
else ShowMessage('未找到');
finally list.Free; end;
end;
end.
IncludeTrailingPathDelimiter 確保路徑結尾有反斜槓,避免雙反斜槓或缺失。FindFirst 可能因權限不足拋出異常,建議包裹 try..except。\\?\ 前綴並調用 Unicode 版 API (FindFirstW)。TTask/TThreadPool 並行遍歷不同分支,最後合併結果。var Cancel: Boolean 參數,遞歸中定期檢查以支持用戶取消。掌握 FindFirst/FindNext/FindClose 遞歸遍歷模式,即可實現 Windows 級別的全盤文件搜尋功能。代碼結構清晰、資源管理嚴謹,是 Delphi 文件系統操作的基石技能。