delphi在目录中搜索文件
在目录中找文件是程序设计中的基本功之一。在应用程序中,我们要知道某个支持文件是否存在,除了在注册表中找到它的行踪外,还需要知道它处在哪个目录下。有时候,注册表中没有某些文件的目录指向,那我们就要直接从磁盘中找到它。
windows系统为我们找文件提供了一个查找功能,它是在外部执行的,我们不能在程序中调用它。
要编写一个自己的文件查找程序,需注意一下几个难点:
(1)要将制定目录细分,因为目录中有子目录,子目录中又有子目录,目录的层次是未知的,所以要将目录中的所有子目录找出来。
(2)文件有多种属性之分,有隐含文件、只读文件、存档文件等,要将它们一并找出来。
如图所示,本例写了一个通用的文件查找过程,首先在Edit1中输入要查找的目录,再在Edit2中输入要找的文件,可以用通配符*号匹配未知内容,然后按“搜索”按钮(Button控件),程序开始寻找文件,并将结果放入ListBox1中。
delphi在目录中搜索文件
delphi在目录中搜索文件
为此,本例写了两个重要的过程,一个是在目录中找文件过程SearcFile,它的参数规定如下:
path:目录名
filename:文件名
list:找到文件后所保存的字符串列表
procedure Tform1.SearchFile(path,filename:string;list:TStrings);
var
sr:TSearchRec;
iAttributes:Integer;
begin
iAttributes:=0;
iAttributes:=iAttributes or faHidden;
if (FindFirst(path+''+filename,iAttributes,sr)=0) then
begin
list.Add(path+''+sr.Name);
while (FindNext(sr)=0) do
begin
list.Add(path+''+sr.Name);
end;
FindClose(sr);
end;
end;
这个过程中主要用到了FindFirst与FindNext函数,这是一对孪生兄弟,伴随着它们,有一个TSearchRec结构,这个结构式这样定义的:
struct TSearchRec{
int Time; //日期
int Size; //大小
int Attr; //属性
AnsiString Name;//名称
int ExcludeAttr;//额外属性
int FindHandle; //找到句柄
_WIN32_FIND_DATAA FindData;
//其他附加信息,包括产生日期、修改日期、长短文件名等
};
在这个结构中,属性是最重要的,它有如下表所示的取值。
属性Attr的取值及说明
值 说明
faReadOnly 只读文件
faHidden 隐含文件,不可见
faSysFile 系统文件
faVolumeID 卷标文件
faDirectory 目录
faArchive 存档文件
faAnyFile 任何文件
这两个函数使用后,别忘了还有一个关闭寻找功能的函数FindClose。
同样,利用FindFirst与FindNext函数,我们再写一个找目录的过程SearchPath,它的参数与上面的过程一样。
procedure Tform1.SearchPath(path,filename:string;list:TStrings);
var
sr:TSearchRec;
iAttributes:Integer;
begin
iAttributes:=0;
iAttributes:=iAttributes or faDirectory;
SearchFile(path,filename,list);
if (FindFirst(path+'*.*',iAttributes,sr)=0) then
begin
if (sr.Attr = iAttributes) then
begin
if((sr.Name<>'.') and (sr.Name<>'..')) then
begin
SearchPath(path+''+sr.Name,filename,list);
end;
end;
while (FindNext(sr) = 0) do
begin
if (sr.Attr = iAttributes) then
begin
if((sr.Name<>'.') and (sr.Name<>'..')) then
begin
SearchPath(path+''+sr.Name,filename,list);
end;
end;
end;
FindClose(sr);
end;
end;
细心的读者可以看出,这是一个递归过程,什么叫递归过程?一句话,就是自己调用自己的过程。
这是最典型的递归过程(或函数)的例子,在什么情况下用递归过程,有些初学程序编写的读者可能难以掌握,想一想该例的实际情况,就是递归的最好例证。
分析一下该例的递归情况:
(1)在指定目录下查找相关文件。
(2)在指定目录下找子目录,若找到子目录,将该子目录作为制定目录,调用自己。
这就是一个不断重复调用自己找目录、找文件的过程,并且这些目录层次都是未知的,用递归的方法实现它是最好不过的了。
本函数中用FindFirst函数所赋的参数为path+"\*.*";为什么要用*.*,因为目录时未知的,在未知情况下,一般采用这种方法才能将所有目录找全。“*”在dos中是通配符的意思。
在找目录过程中,程序会找到“.”、“..”这样的目录,使用过dos的朋友一定明白,“.”代表当前目录,“..”代表上层目录,在这里忽略它就可以了。
搜索按钮Button1实现代码如下:
procedure TForm1.Button1Click(Sender: TObject);
begin
SearchPath(Edit1.Text,Edit2.Text,ListBox1.Items);
end;