delphi - FindfirstEx using recursion -
it drives me nuts (i'll should learn recursion though) i'll can't make work, i'm doing wrong.
i trying make exact copy of findfirst code below findfirstex on recursion i'll got stackoverflow , lot of strange things happen i'll guess must wrong way using i'll removed , replace comment i'm stuck here...
so i'll need procedure i'm able specify directory , file mask thats it.
procedure fetchfilesandfolders(apath, amask; lbsearchresult: tmemo); const find_first_ex_large_fetch = 2; var hfile: cardinal; searchresult: win32_find_dataw; begin lbsearchresults.lines.beginupdate; hfile := findfirstfileex(pchar(apath + amask), findexinfostandard, @searchresult, findexsearchnamematch, nil, find_first_ex_large_fetch); if (hfile <> invalid_handle_value) begin try repeat if (searchresult.dwfileattributes , fadirectory = fadirectory) begin lbsearchresult.lines.append(includetrailingbackslash(apath) + string(searchresult.cfilename)); end else begin // i'm stuck here... end; until (not findnextfile(hfile, searchresult)) winapi.windows.findclose(hfile);; lbsearchresult.lines.endupdate; end; something findfirstfileex instead:
procedure filesearch(const dirname, amask: string; lbsearchresult: tmemo); var searchresult: tsearchrec; begin lbsearchresult.lines.beginupdate; if findfirst(dirname+ amask, faanyfile, searchresult) = 0 begin try repeat if (searchresult.attr , fadirectory) = 0 begin lbsearchresult.lines.append(includetrailingbackslash(dirname) + searchresult.name); end else if (searchresult.name <> '.') , (searchresult.name <> '..') begin filesearch(includetrailingbackslash(dirname) + searchresult.name, lbsearchresult); end; until findnext(searchresult) <> 0 findclose(searchresult); lbsearchresult.lines.endupdate; end; end; end; so i'll need show me doing right. thank you!
version 3 (still not working no exception):
procedure filesearch(const apath, amask: string; lbsearchresult: tmemo); const find_first_ex_large_fetch = 2; var hfile: cardinal; searchresult: win32_find_dataw; begin lbsearchresult.lines.beginupdate; hfile := findfirstfileex(pchar(apath + amask), findexinfostandard, @searchresult, findexsearchnamematch, nil, find_first_ex_large_fetch); if (hfile <> invalid_handle_value) begin try repeat if (0 = (searchresult.dwfileattributes , file_attribute_directory)) begin lbsearchresult.lines.add(includetrailingbackslash(apath) + string(searchresult.cfilename)); end else begin if (searchresult.cfilename <> string('.')) , (searchresult.cfilename <> '..') lbsearchresult.lines.add(includetrailingbackslash(apath) + string(searchresult.cfilename)); // following not good, infinite!!! // filesearch(apath, amask, lbsearchresult); end; until (not findnextfile(hfile, searchresult)) winapi.windows.findclose(hfile);; lbsearchresult.lines.endupdate; end; end; end; all files , folders shown inside test folder not deeper no recursion...
filesearch('d:\projects\test\', '*.*', memo1); so example:
d:\projects\test\blubb
is shown not files inside or directories test\blubb\
the cause of infinite recursion appears omitting test files '.' , '..'.
in second code there line
else if (searchresult.name <> '.') , (searchresult.name <> '..') these 2 values special directories mean 'current directory' , 'parent directory' respectively. while analysing current directory find 'subdirectory' called '.', pointer directory analysing. therefore recursive call subdirectory analyse same directory again, during again find directory '.' , again attempt analyse same directory, , on ever.
a similar situation arises '..' analyse parent directory.
it critical test not omitted.
note on version 3
one of pet hates not including begin...end blocks in if statements, , 3rd version seems illustrate why. still infinite loop because if statement not apply recursion - must apply.
the second, more serious issue parameters of recursive call same original call. can think of no circumstances ever valid (although sure correct me). instead must call name of child directory. have added new variable fnewpath simplify things.
procedure filesearch(const apath, amask: string; lbsearchresult: tmemo); const find_first_ex_large_fetch = 2; var hfile: cardinal; searchresult: win32_find_dataw; fnewpath : string; begin lbsearchresult.lines.beginupdate; hfile := findfirstfileex(pchar(apath + amask), findexinfostandard, @searchresult, findexsearchnamematch, nil, find_first_ex_large_fetch); if (hfile <> invalid_handle_value) begin try repeat if (0 = (searchresult.dwfileattributes , file_attribute_directory)) begin lbsearchresult.lines.add(includetrailingbackslash(apath) + string(searchresult.cfilename)); end else begin if (searchresult.cfilename <> string('.')) , (searchresult.cfilename <> '..') begin // <------------------- fnewpath := includetrailingbackslash(apath) + string(searchresult.cfilename); lbsearchresult.lines.add( fnewpath ); filesearch(fnewpath, amask, lbsearchresult); end; //<--------------- recurstion *must* covered if statement end; until (not findnextfile(hfile, searchresult)); winapi.windows.findclose(hfile); lbsearchresult.lines.endupdate; end; end; end;
Comments
Post a Comment