添加预处理目录功能,可以用以控制搜索目录的深度。
{*------------------------------------------------------------------------------
File Seeker is a class for searching files and subfolders under the given
folder. Deriving form TFileSeeker and overriding the process functions can
process the found files and folders.
Copyright (c) 2007 Johnny
@author Johnny
@version 2007/03/11 Johnny v1.0 Initial version
@version 2007/03/17 Johnny v1.1 Added directory not exists exception and Setup
@version 2007/03/24 Johnny v1.2 Added PreProcessFolder function
-------------------------------------------------------------------------------}
unit FileSeeker;
interface
uses
Windows, SysUtils;
type
/// The base class for searching files and subfolders
TFileSeeker = class
private
FSearchSubfolders: Boolean; /// Whether search subfolders or not
FFileFilter: string; /// File filter for searching
FPreProcessFolders: Boolean; /// Whether preprocess found folders
FProcessFolders: Boolean; /// Whether process found folders or not
FProcessFiles: Boolean; /// Whether process found files or not
function DoSearch(Folder: string; const Layer: Integer): Boolean;
protected
function PreProcessFolder(const Folder: string;
const Layer: Integer): Boolean; virtual;
function DoProcessFolder(const Folder: string;
const Layer: Integer): Boolean; virtual;
function DoProcessFile(const FileName: string;
const Layer: Integer): Boolean; virtual;
procedure Setup(const Folder: string); virtual;
public
constructor Create(const SearchSubfolders: Boolean;
const FileFilter: string; const PreProcessFolders, ProcessFolders,
ProcessFiles: Boolean);
function Search(const Folder: string): Boolean;
end;
/// Directory not exists exception
EDirectoryNotExists = class(Exception);
implementation
{ TFileSeeker }
{*------------------------------------------------------------------------------
The constructor of TFileSeeker class. Derived classes can override it and
set the properties.
@param SearchSubfolders Whether search subfolders or not
@param FileFilter File Filter for searching
@param ProcessFolders Whether process found folders or not
@param ProcessFiles Whether process found files or not
-------------------------------------------------------------------------------}
constructor TFileSeeker.Create(const SearchSubfolders: Boolean;
const FileFilter: string; const PreProcessFolders, ProcessFolders,
ProcessFiles: Boolean);
begin
FSearchSubfolders := SearchSubfolders;
FFileFilter := FileFilter;
FPreProcessFolders := PreProcessFolders;
FProcessFolders := ProcessFolders;
FProcessFiles := ProcessFiles;
end;
{*------------------------------------------------------------------------------
Search files recursively.
@param Folder The current folder for searching
@param Layer The current folder layer, for the process functions
@return True if the searching is terminated, False otherwise
-------------------------------------------------------------------------------}
function TFileSeeker.DoSearch(Folder: string; const Layer: Integer): Boolean;
var
SearchHandle: Cardinal;
FileData: TWin32FindData;
FileName: string;
begin
Result := False;
Folder := IncludeTrailingPathDelimiter(Folder);
if FPreProcessFolders and PreProcessFolder(Folder, Layer) then
Exit;
if FProcessFolders then
begin
Result := DoProcessFolder(Folder, Layer);
if Result then
Exit;
end;
SearchHandle := FindFirstFile(PChar(Folder + FFileFilter), FileData);
if SearchHandle <> INVALID_HANDLE_VALUE then
begin
repeat
FileName := FileData.cFileName;
if (FileName = '.') or (FileName = '..') then
Continue;
FileName := Folder + FileName;
if FileData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY <> 0 then
begin
if FSearchSubfolders then
Result := DoSearch(FileName, Layer + 1);
end
else
begin
if FProcessFiles then
Result := DoProcessFile(FileName, Layer);
end;
if Result then
Break;
until not FindNextFile(SearchHandle, FileData);
Windows.FindClose(SearchHandle);
end;
end;
{*------------------------------------------------------------------------------
The function to preprocess found folders. It does nothing except returning
False. Derived classes can override it to determine whether to stop the
searching under the folder, but not the whole searching.
@param Folder The found folder, maybe the base folder
@param Layer The layer of the found folder relative to the base folder
@return True to stop the searching under the folder, but not the whole
searching
-------------------------------------------------------------------------------}
function TFileSeeker.PreProcessFolder(const Folder: string;
const Layer: Integer): Boolean;
begin
Result := False;
end;
{*------------------------------------------------------------------------------
The function to process found files. It does nothing except returning False.
Derived classes should override it to process found files.
@param FileName The filename of the found file
@param Layer The layer of the found file relative to the base folder
@return True to terminate the searching, False otherwise
-------------------------------------------------------------------------------}
function TFileSeeker.DoProcessFile(const FileName: string;
const Layer: Integer): Boolean;
begin
Result := False;
end;
{*------------------------------------------------------------------------------
The function to process found folders. It does nothing except returning False.
Derived classes should override it to process found folders.
@param Folder The found folder, maybe the base folder
@param Layer The layer of the found folder relative to the base folder
@return True to terminate the searching, False otherwise
-------------------------------------------------------------------------------}
function TFileSeeker.DoProcessFolder(const Folder: string;
const Layer: Integer): Boolean;
begin
Result := False;
end;
{*------------------------------------------------------------------------------
Search files, calling DoSearch function.
@param Folder The base folder for searching
@return True if the searching is terminated by the process functions, False
otherwise
@throws EDirectoryNotExists Directory no exists
-------------------------------------------------------------------------------}
function TFileSeeker.Search(const Folder: string): Boolean;
begin
if not DirectoryExists(Folder) then
raise EDirectoryNotExists.CreateFmt('Directory "%s" no exists', [Folder])
else
begin
Setup(Folder);
Result := DoSearch(Folder, 0);
end;
end;
{*------------------------------------------------------------------------------
Do some setups before searching
@param Folder The base folder for searching
-------------------------------------------------------------------------------}
procedure TFileSeeker.Setup(const Folder: string);
begin
// Do nothing
end;
end.