首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 實現遞歸遍歷子目錄文件查詢:FindFirst/FindNext/FindClose 完整實踐

     編輯:Delphi

前言

Windows 檔案搜尋功能能遍歷所有子目錄,其核心是遞歸遍歷目錄樹。本文展示如何在 Delphi 中使用 FindFirst/FindNext/FindClose API 結合遞歸函數,實現指定根目錄下所有層級子目錄的文件查詢,返回完整路徑列表。

核心 API 速查

函數用途
FindFirst(Path, Attr, SearchRec)查找第一個匹配項,返回 0 表示成功
FindNext(SearchRec)查找下一個匹配項,返回 0 表示成功
FindClose(SearchRec)釋放搜尋句柄資源
FileExists(FileName)快速判斷文件是否存在

遞歸算法邏輯

  1. 獲取當前目錄下所有子目錄名(屬性 faDirectory,排除 . 和 ..),存入字串列表。
  2. 在當前目錄查找目標文件,存在則加入結果列表。
  3. 對每個子目錄遞歸調用查詢函數(路徑拼接 子目錄名 + '\')。
  4. 釋放字串列表,返回是否找到。

關鍵代碼實現

1. 判斷有效子目錄

function IsValidDir(SearchRec: TSearchRec): Boolean;
begin
  Result := (SearchRec.Attr = faDirectory) and
            (SearchRec.Name <> '.') and
            (SearchRec.Name <> '..');
end;

2. 遞歸查詢主函數

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;

3. 調用示例

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。
  • 長路徑支援:Windows 260 字元限制,啟用長路徑需在路徑前加 \\?\ 前綴並調用 Unicode 版 API (FindFirstW)。
  • 並行化:大規模目錄樹可使用 TTask/TThreadPool 並行遍歷不同分支,最後合併結果。
  • 取消機制:傳入 var Cancel: Boolean 參數,遞歸中定期檢查以支持用戶取消。

總結

掌握 FindFirst/FindNext/FindClose 遞歸遍歷模式,即可實現 Windows 級別的全盤文件搜尋功能。代碼結構清晰、資源管理嚴謹,是 Delphi 文件系統操作的基石技能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved