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

时间:2011-06-30 14:40:37

标签: delphi

我已经在Delphi中实现了这个代码,它将搜索文件或给出的名称,但它省略了搜索所有子目录。怎么办呢?

代码:

 if FindFirst(filePath,faAnyFile,searchResult)=0 then
  try
    repeat
    lbSearchResult.Items.Append(searchResult.Name);

    until FindNext(searchResult)<>0
  except
  on e:Exception do
  ShowMessage(e.Message);
  end; //try ends
  FindClose(searchResult); 

5 个答案:

答案 0 :(得分:24)

使用Delphi XE及以上版本,您可以查看IOUtils.pas:

TDirectory.GetFiles('C:\', '*.dll', TSearchOption.soAllDirectories);

答案 1 :(得分:9)

如果您不需要线程,最简单的方法是:

procedure TForm1.AddAllFilesInDir(const Dir: string);
var
  SR: TSearchRec;
begin
  if FindFirst(IncludeTrailingBackslash(Dir) + '*.*', faAnyFile or faDirectory, SR) = 0 then
    try
      repeat
        if (SR.Attr and faDirectory) = 0 then
          ListBox1.Items.Add(SR.Name)
        else if (SR.Name <> '.') and (SR.Name <> '..') then
          AddAllFilesInDir(IncludeTrailingBackslash(Dir) + SR.Name);  // recursive call!
      until FindNext(Sr) <> 0;
    finally
      FindClose(SR);
    end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ListBox1.Items.BeginUpdate;
  AddAllFilesInDir('C:\Users\Andreas Rejbrand\Documents\Aweb');
  ListBox1.Items.EndUpdate;
end;

答案 2 :(得分:4)

最简单的方法是:

uses
  DSiWin32;

DSiEnumFilesToStringList('c:\somefolder\file.name', 0, ListBox1.Items, true, true);

DSiWin32是一个免费的Delphi库。

答案 3 :(得分:1)

当我需要像tricks那样覆盖受保护的方法时,我倾向于使用通用的解决方案来解决这个问题......我对这个类进行了攻击。

以下是TDirectoryListbox

的使用方法

在每个表单上,您需要使用此hacked TDirectoryListbox,只需将unitTDirectoryListbox_WithHiddenAndSystemFolders添加到界面uses,表单就会使用hacked {{ 1}}。

在proyect文件夹中创建一个名为TDirectoryListbox的文件。

将此文本放在该文件中(稍后我将解释我所做的):

unitTDirectoryListbox_WithHiddenAndSystemFolders.pas

现在我解释一下我做了什么:

  • 通过将unit unitTDirectoryListbox_WithHiddenAndSystemFolders; interface uses Windows ,SysUtils ,Classes ,FileCtrl ; type TDirectoryListbox=class(FileCtrl.TDirectoryListbox) private FPreserveCase:Boolean; FCaseSensitive:Boolean; protected function ReadDirectoryNames(const ParentDirectory:String;DirectoryList:TStringList):Integer; procedure BuildList;override; public constructor Create(AOwner:TComponent);override; destructor Destroy;override; property PreserveCase:Boolean read FPreserveCase; property CaseSensitive:Boolean read FCaseSensitive; end; implementation constructor TDirectoryListbox.Create(AOwner:TComponent); begin inherited Create(AOwner); end; destructor TDirectoryListbox.Destroy; begin inherited Destroy; end; function TDirectoryListbox.ReadDirectoryNames(const ParentDirectory:String;DirectoryList:TStringList):Integer; var TheCount,Status:Integer; SearchRec:TSearchRec; begin TheCount:=0; Status:=FindFirst(IncludeTrailingPathDelimiter(ParentDirectory)+'*.*',faDirectory or faHidden or faSysFile,SearchRec); try while 0=Status do begin if faDirectory=(faDirectory and SearchRec.Attr) then begin if ('.'<>SearchRec.Name) and ('..'<>SearchRec.Name) then begin DirectoryList.Add(SearchRec.Name); Inc(TheCount); end; end; Status:=FindNext(SearchRec); end; finally FindClose(SearchRec); end; ReadDirectoryNames:=TheCount; end; procedure TDirectoryListBox.BuildList; var TempPath: string; DirName: string; IndentLevel, BackSlashPos: Integer; VolFlags: DWORD; I: Integer; Siblings: TStringList; NewSelect: Integer; Root: string; begin try Items.BeginUpdate; Items.Clear; IndentLevel := 0; Root := ExtractFileDrive(Directory)+'\'; GetVolumeInformation(PChar(Root), nil, 0, nil, DWORD(i), VolFlags, nil, 0); FPreserveCase := VolFlags and (FS_CASE_IS_PRESERVED or FS_CASE_SENSITIVE) <> 0; FCaseSensitive := (VolFlags and FS_CASE_SENSITIVE) <> 0; if (Length(Root) >= 2) and (Root[2] = '\') then begin Items.AddObject(Root, OpenedBMP); Inc(IndentLevel); TempPath := Copy(Directory, Length(Root)+1, Length(Directory)); end else TempPath := Directory; if (Length(TempPath) > 0) then begin if AnsiLastChar(TempPath)^ <> '\' then begin BackSlashPos := AnsiPos('\', TempPath); while BackSlashPos <> 0 do begin DirName := Copy(TempPath, 1, BackSlashPos - 1); if IndentLevel = 0 then DirName := DirName + '\'; Delete(TempPath, 1, BackSlashPos); Items.AddObject(DirName, OpenedBMP); Inc(IndentLevel); BackSlashPos := AnsiPos('\', TempPath); end; end; Items.AddObject(TempPath, CurrentBMP); end; NewSelect := Items.Count - 1; Siblings := TStringList.Create; try Siblings.Sorted := True; { read all the dir names into Siblings } ReadDirectoryNames(Directory, Siblings); for i := 0 to Siblings.Count - 1 do Items.AddObject(Siblings[i], ClosedBMP); finally Siblings.Free; end; finally Items.EndUpdate; end; if HandleAllocated then ItemIndex := NewSelect; end; end. 添加到接口unitTDirectoryListbox_WithHiddenAndSystemFolders,我使表单使用修改后的(aka,uses)组件。
  • 我开始复制名为hacked的受保护方法(需要修改的方法),我从单位ReadDirectoryNames复制它,然后我在我自己的单位上编辑该副本到FileCtrl问题(没有显示隐藏文件夹,也没有显示系统文件夹); fix是通过在trick部分FindFirst之后添加来编辑对faDirectory的调用,我还将or faHidden or faSysFile更改为SlashSep(避免一些额外的引用,等),并进行重新格式化(索引等),所以我可以看到该方法是我修改过的。
  • 然后我会关注缺少的内容......例如IncludeTrailingPathDelimiter,我只是简单地从单位BuildList复制它而不做任何修改(如果没有复制,FileCtrl不起作用,因为对hack的调用位于ReadDirectoryNames)内。
  • 然后我复制BuildListFPreserveCase的声明及其属性声明(它们在FCaseSensitive方法中使用)。
  • 就是这样,现在修改后的BuildList会看到隐藏的和系统文件夹

希望这对其他人有帮助,这样你就可以在你的项目中同时拥有TDirectoryListBox(原始的和修改过的)(但不是同一个形式,抱歉),而根本不需要修改VCL。

PD:有额外知识的人可能能够添加属性来配置它是否必须显示或不显示隐藏和/或系统文件夹作为改进,它一定不是非常难以理解,两个私有布尔变量及其对应的{{1使用读取和写入方法的声明...我没有这样做,因为我不仅要添加这样的两个,还要添加SymLinks等(在单元TDirectoryListBox上搜索property并查看有多少有很多工作要加上它们,对不起给您带来任何不便。

答案 4 :(得分:0)

我在不久前发布了一个针对不同问题的解决方案:

Delphi: Copy Files from folder with Overall progress. CopyFileEx?