Reputation: 76577
I need to do some searching in the filesystem and would like to present a progress indication.
A rough approximation of that is the number of directories traversed.
function GetSubDirCount(Path : String): integer;
var
Index : Integer;
Temp : String;
SearchRec : TSearchRec;
begin
Result:= 0;
Temp:= Path;
if Path[Length(Path)] <> SysUtils.PathDelim then begin
Path:= Path + SysUtils.PathDelim;
end;
Path:= Path + '*.';
Index:= FindFirst(Path, faDirectory, SearchRec);
while Index = 0 do begin
if (SearchRec.Name = '.') or (SearchRec.Name = '..') then begin
Index:= FindNext(SearchRec);
Continue;
end;
Inc(Result);
Result:= Result + GetSubDirCount(Temp + SysUtils.PathDelim + SearchRec.Name);
Index:= FindNext(SearchRec);
end;
FindClose(SearchRec);
end;
I currently use the above code, is there a faster way?
I'm only interested in the count.
If there's a really fast way to get the number of files as well that would be a bonus.
Upvotes: 1
Views: 1326
Reputation: 9096
@Johan Since the Windows code takes up most time, I suggest you apply the fixes suggested by other respondents, and update your code to use threads if your feel comfortable with that:
As soon as you retrieve a subdirectory put add it to a (thread safe) list
Have a thread look at that list and spawn worker threads do to the actual file processing per directory
Update your progress all the time: number of dirs found/handled. This will be a bit wobbly in the beginning, but at least you can start working while Windows is still 'finding'
The 'usual' warnings apply:
don't make your number of threads too large
if your file processing creates new files make sure your find routines don't choke on the new output files
Upvotes: 0
Reputation: 15817
Minor improvement: use const in the parameter declaration. ex:
function GetSubDirCount(const Path : String): integer;
As Rob points out, this will not work as Path is modified in the body. I would still use this approach however, and NOT modify path in the body. I'd have a local string var "Suffix", modify that (add optional pathdelim, and '*.'), and pass both to FindFirst:
FindFirst(Path+Suffix, faDirectory, SearchRec);
Upvotes: 0
Reputation: 47714
As you are not specifying the Delphi version you are using, I suggest the corresponding methods from IOUtils - namely TDirectory.GetDirectories and TDirectory.GetFiles as they are available in recent Delphi versions.
Update: It is probably not the fastest way to count the number of directories and files, but if the files shall be iterated later anyway, one could as well use the result of these functions for the iteration.
Upvotes: 4