如何通过Delphi中的所有子目录搜索文件

时间:2011-07-01 09:29:38

标签: delphi delphi-7

我实现了这段代码,但我又无法搜索子目录。

     procedure TFfileSearch.FileSearch(const dirName:string);
     begin
//We write our search code here
  if FindFirst(dirName,faAnyFile or faDirectory,searchResult)=0 then
  begin
    try
      repeat
      ShowMessage(IntToStr(searchResult.Attr));
        if (searchResult.Attr and faDirectory)=0 then   //The Result is a File
        //begin
          lbSearchResult.Items.Append(searchResult.Name)
         else 
         begin
            FileSearch(IncludeTrailingBackSlash(dirName)+searchResult.Name);
           //
         end;
       until FindNext(searchResult)<>0
     finally
     FindClose(searchResult);
     end;
   end;
   end;
    procedure TFfileSearch.btnSearchClick(Sender: TObject);
   var
 filePath:string;
begin
lbSearchResult.Clear;
if Trim(edtMask.Text)='' then
  MessageDlg('EMPTY INPUT', mtWarning, [mbOK], 0)
else
begin
  filePath:=cbDirName.Text+ edtMask.Text;
  ShowMessage(filePath);
  FileSearch(filePath);

end;

端;

我在E:\驱动器中搜索* .ini文件。所以最初filePath是E:*。ini。 但代码不会搜索E:\ drive中的目录。如何纠正?

先谢谢

5 个答案:

答案 0 :(得分:9)

FindFirst的调用中,您无法对文件扩展名应用限制。如果您这样做,那么目录不会被枚举。相反,您必须在代码中检查匹配的扩展名。尝试这样的事情:

procedure TMyForm.FileSearch(const dirName:string);
var
  searchResult: TSearchRec;
begin
  if FindFirst(dirName+'\*', faAnyFile, searchResult)=0 then begin
    try
      repeat
        if (searchResult.Attr and faDirectory)=0 then begin
          if SameText(ExtractFileExt(searchResult.Name), '.ini') then begin
            lbSearchResult.Items.Append(IncludeTrailingBackSlash(dirName)+searchResult.Name);
          end;
        end else if (searchResult.Name<>'.') and (searchResult.Name<>'..') then begin
          FileSearch(IncludeTrailingBackSlash(dirName)+searchResult.Name);
        end;
      until FindNext(searchResult)<>0
    finally
      FindClose(searchResult);
    end;
  end;
end;

procedure TMyForm.FormCreate(Sender: TObject);
begin
  FileSearch('c:\windows');
end;

答案 1 :(得分:3)

我讨厌使用FindFirst / FindNext的那些递归解决方案,我认为有些甚至忘记使用FindClose来清理资源很麻烦。因此,为了它的乐趣,一个非递归的解决方案应该是实用的...

procedure FindDocs(const Root: string);
var
  SearchRec: TSearchRec;
  Folders: array of string;
  Folder: string;
  I: Integer;
  Last: Integer;
begin
  SetLength(Folders, 1);
  Folders[0] := Root;
  I := 0;
  while (I < Length(Folders)) do
  begin
    Folder := IncludeTrailingBackslash(Folders[I]);
    Inc(I);
    { Collect child folders first. }
    if (FindFirst(Folder + '*.*', faDirectory, SearchRec) = 0) then
    begin
      repeat
        if not ((SearchRec.Name = '.') or (SearchRec.Name = '..')) then
        begin
          Last := Length(Folders);
          SetLength(Folders, Succ(Last));
          Folders[Last] := Folder + SearchRec.Name;
        end;
      until (FindNext(SearchRec) <> 0);
      FindClose(SearchRec);
    end;
    { Collect files next.}
    if (FindFirst(Folder + '*.doc', faAnyFile - faDirectory, SearchRec) = 0) then
    begin
      repeat
        if not ((SearchRec.Attr and faDirectory) = faDirectory) then
        begin
          WriteLn(Folder, SearchRec.Name);
        end;
      until (FindNext(SearchRec) <> 0);
      FindClose(SearchRec);
    end;
  end;
end;

虽然它似乎占用了大量内存,因为它使用动态数组,但递归方法将完全相同,但递归发生在堆栈上!此外,使用递归方法,为所有局部变量分配空间,而我的解决方案仅为文件夹名称分配空间。
检查速度时,两种方法都应该一样快。但是,递归方法更容易记住。您也可以使用TStringList而不是动态数组,但我只喜欢动态数组 我的解决方案的另一个技巧:它可以在多个文件夹中搜索!我只使用一个根初始化了文件夹数组,但您可以轻松地将其长度设置为3,并将文件夹[0]设置为C:\,文件夹[1]设置为D:\和文件夹[2]设置为E:\并且它将搜索多个磁盘!

顺便说一下,用你想要执行的任何逻辑替换WriteLn()代码......

答案 2 :(得分:3)

我建议如下操作:

uses
  System.Types,
  System.IOUtils;

procedure TForm7.Button1Click(Sender: TObject);
var
  S: string;
begin
  Memo1.Lines.Clear;
  for S in TDirectory.GetFiles('C:\test', '*.bmp', TSearchOption.soAllDirectories) do
    Memo1.Lines.Add(S);
  Showmessage('Pronto!');
end;

答案 3 :(得分:-1)

这个文件搜索的问题是它会无限循环,FindClose就像它不存在一样。

答案 4 :(得分:-3)

procedure FindFilePattern(root:String;pattern:String);
var
  SR:TSearchRec;
begin
  root:=IncludeTrailingPathDelimiter(root);
  if FindFirst(root+'*.*',faAnyFile,SR) = 0 then
  begin
      repeat
          Application.ProcessMessages;
          if ((SR.Attr and faDirectory) = SR.Attr ) and (pos('.',SR.Name)=0) then
             FindFilePattern(root+SR.Name,pattern)
          else
          begin
           if pos(pattern,SR.Name)>0 then Form1.ListBox1.Items.Add(Root+SR.Name);
          end;
      until FindNext(SR)<>0;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  FindFilePattern('C:\','.exe');
end;

以递归方式搜索显示包含特定模式的文件名的所有文件夹。