2011-07-01 23 views
2

このコードを実装しましたが、もう一度サブディレクトリを検索することはできません。Delphiのすべてのサブディレクトリでファイルを検索するには

 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; 

end;

E:\ドライブに* .iniファイルの検索を指定しています。最初のfilePathはE:* .iniです。 しかし、コードはE:\ドライブのディレクトリを検索しません。それを修正するには?あなたはFindFirstへの呼び出しでファイルの拡張子に制限を適用することはできませんアドバンス

+0

http://stackoverflow.com/questions/ 6536525/delphi/6536733#6536733 –

答えて

9

感謝。あなたがそうした場合、ディレクトリは列挙されません。代わりに、コード内の一致する拡張子をチェックする必要があります。

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; 
+5

ファイルの拡張子に*を適用することはできません*ディレクトリは列挙されません。 –

+0

@Sertacありがとう。私は不正確で、それに応じて答えを更新しました。 –

+0

また、ディレクトリが見つかる場合でも、 'C:\ SomeDir'と言うと、' C:\ *。ini \ SomeDir \ 'を検索することはできません。 –

-2
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; 

これは、特定のパターンを含むファイル名を表示するすべてのフォルダに再帰的に検索します。このような何かを試してみてください。

+0

このコードは、ファイル属性と名前を誤って比較しており、検索ハンドルが漏れています。 –

5

私は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を使うこともできますが、私は動的配列が好きです。
私の解決策でもう1つのトリック:それは複数のフォルダで検索できます!私は1つのルートでフォルダ配列を初期化しましたが、長さを3に簡単に設定でき、Folders [0]をC:\、Folders [1]をD:\、Folders [2]をE:\に設定すると、複数のディスクで検索します!ところで

、実行したいものは何でもロジックとのwriteln()のコードを置き換え...

+2

'SetLength(..、Length()+ 1)'を使用しなかった場合、これを投票します。 –

+0

'SetLength(..、Length()+ 1)'の何が問題なのですか?むしろ、より大きなバッファを割り当てるでしょうか?代わりにリンクリストを使用しますか?フォルダリストを維持するためのTStringList?選択肢はたくさんあります。 –

+2

文字列リストが私の選択です。 'SetLength(..、Length()+ 1)'はメモリの断片化につながる可能性があります。 –

1

私は次のようにやってお勧めします:

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; 
+0

こんにちは!あなたが貼り付けたコードの説明をあなたに与えてくれたことはとても嬉しいです。ありがとう! –

+0

このコードスニペットは問題を解決するかもしれませんが、[説明を含む](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers)は、あなたの質を改善するのに本当に役立ちます役職。将来読者の質問に答えていることを覚えておいてください。そうした人々はあなたのコード提案の理由を知らないかもしれません。 –

関連する問題