Mega Code Archive

 
Categories / Delphi / Files
 

File & directory iterator

Title: File & directory iterator Question: The visitor pattern comes in very useful when requiring code to iterate directories. The pattern provides an object that calls back to a method that has been assigned to it for each element it iterates through. In this case it is a simple delphi event and we are iterating thorught directories and files. To use, simply create an instance of the TFileIterator object, assign it a callback method, then call exceute passing in the directory to scan, a file spec e.g. *.txt for all .txt files and a either fitSingleDirectory or fitIncludeSubDirectories to choose to scan just he specified directory or all directories. Your method will be called for every file that matches the criteria, passign the directory the iterator is currently processed, and the TSearchrec for the file it is currenlty on. If you want your call back to be called for directories as well then rem out the directory attribute check around the call to the callback. (line 70ish) Answer: {* Generic File Iterator unit (c) Matt Harrison 2004 visit lummie.co.uk. This unit provides an iterator methods and a standard callback event to allow quick iteration of files in directories. Create an instance, assign a callback event and call execute. NOTE : As the object is interfaced (and therefore referenced counted) you do not need to free it. If the callback returns true at any point the iterator will exit and exceute will return true. This allows itterations to be cancelled. e.g. FI := TFileIterator.create; FI.CallBack := MyCallBackEvent; Quitted := FI.execute('C:\windows','*.*', fitSingleDirectory); *} unit FileIterater; interface uses classes, sysutils; type TFileIteratorCallBackEvent = function (Directory : string; FoundFile : TSearchRec) : boolean of object; TFileIteratorType = (fitSingleDirectory, fitIncludeSubDirectories); TFileIterator = class(TInterfacedObject) private FCallback: TFileIteratorCallBackEvent; public procedure AfterConstruction; override; function Execute(Directory : string; FileSpec : string; ExecuteType : TFileIteratorType) : boolean; property Callback : TFileIteratorCallBackEvent read FCallback write FCallback; end; implementation { TFileIterator } procedure TFileIterator.AfterConstruction; begin inherited; FCallback := nil; end; function TFileIterator.Execute(Directory : string; FileSpec : string; ExecuteType : TFileIteratorType) : boolean; procedure ProcessDir(Directory, FileSpec : string; ExecuteType : TFileIteratorType; var QuitFlag : boolean); var sr : TSearchRec; begin if ExecuteType = fitIncludeSubDirectories then begin // process sub directories if FindFirst(Directory + '*.*', faAnyFile, sr) = 0 then begin repeat if (sr.Attr and faDirectory = faDirectory) and (sr.Name '.') and (sr.Name '..') then // ignore . and .. begin ProcessDir(IncludeTrailingPathDelimiter(Directory + sr.name),FileSpec, ExecuteType, QuitFlag); end; until QuitFlag or (FindNext(sr) 0); FindClose(sr); end; end; if not QuitFlag and (FindFirst(Directory + FileSpec, faAnyFile, sr) = 0) then begin repeat if (sr.Attr and faDirectory = 0) and (sr.Name '.') and (sr.Name '..') then begin QuitFlag := CallBack(Directory,sr); if QuitFlag then break; end; until FindNext(sr) 0; FindClose(sr); end; end; begin result := false; if not assigned(Callback) then raise exception.create('Execute called on TFileIterator with out assigning a callback'); if not DirectoryExists(IncludeTrailingPathDelimiter(Directory)) then raise exception.create('Invlaid directory specified'); ProcessDir(IncludeTrailingPathDelimiter(Directory),FileSpec, ExecuteType, result); end; end.