关于遍历目录及文件算法的问题 ( 积分: 100 )

  • 主题发起人 主题发起人 phenix3344
  • 开始时间 开始时间
P

phenix3344

Unregistered / Unconfirmed
GUEST, unregistred user!
我自己编写了一个遍历指定位置目录及文件的程序,对于指定的一般的目录(如D盘的任意目录)都可以正确遍历,但指定位置为C:或E:时错误,错误现象为遍历的文件数明显少于实际数,我估计可能是我的算法有问题了,请高手指点一下我的程序是哪里的问题。
递归遍历函数:
procedure TForm1.WJMDB(FatherDir: String);
var
iFindResult: integer;
SearchRec: TSearchRec;

begin
FatherDir := ExcludeTrailingPathDelimiter(FatherDir) + '/';
iFindResult := FindFirst(FatherDir + '*.*', faAnyFile , SearchRec);
iFindResult := FindNext(SearchRec); //至此系统两目录 <.> <..>浏览完毕
iFindResult := FindNext(SearchRec);
while iFindResult = 0 do
begin
if SearchRec.Attr = faDirectory then //判断是否是目录
begin
Memo2.Lines.Add(FatherDir + SearchRec.Name);
WJMDB(FatherDir + SearchRec.Name);
end
else
begin
Memo1.Lines.Add(FatherDir + SearchRec.Name);
end;
iFindResult := FindNext(SearchRec);
end;
FindClose(SearchRec);
end;

调用用WJMDB(Edit1.text)

到底是哪里的问题?请指点一下。
谢谢!!!
 
我自己编写了一个遍历指定位置目录及文件的程序,对于指定的一般的目录(如D盘的任意目录)都可以正确遍历,但指定位置为C:或E:时错误,错误现象为遍历的文件数明显少于实际数,我估计可能是我的算法有问题了,请高手指点一下我的程序是哪里的问题。
递归遍历函数:
procedure TForm1.WJMDB(FatherDir: String);
var
iFindResult: integer;
SearchRec: TSearchRec;

begin
FatherDir := ExcludeTrailingPathDelimiter(FatherDir) + '/';
iFindResult := FindFirst(FatherDir + '*.*', faAnyFile , SearchRec);
iFindResult := FindNext(SearchRec); //至此系统两目录 <.> <..>浏览完毕
iFindResult := FindNext(SearchRec);
while iFindResult = 0 do
begin
if SearchRec.Attr = faDirectory then //判断是否是目录
begin
Memo2.Lines.Add(FatherDir + SearchRec.Name);
WJMDB(FatherDir + SearchRec.Name);
end
else
begin
Memo1.Lines.Add(FatherDir + SearchRec.Name);
end;
iFindResult := FindNext(SearchRec);
end;
FindClose(SearchRec);
end;

调用用WJMDB(Edit1.text)

到底是哪里的问题?请指点一下。
谢谢!!!
 
很有意思。。。不过得睡觉了。。。明天上班呢。。。
我觉得问题在你的
begin
Memo2.Lines.Add(FatherDir + SearchRec.Name);
WJMDB(FatherDir + SearchRec.Name);-----这个位置上。。。进到下一级目录后跳不出来了。。。遍历这个下一级目录后就BYE了。。。你再看看吧。。。我睡了先。。。
end
 
无法识别隐藏目录的原因。
if SearchRec.Attr = faDirectory then //判断是否是目录
如果一个目录有隐藏属性,就被识别成一个文件了。你可以试试。我也遇到这样的问题。
关注问题。希望高手指点下。。。
 
因为C:/没有.和..
procedure TForm1.WJMDB(FatherDir: String);
var
iFindResult: integer;
SearchRec: TSearchRec;

begin
FatherDir := ExcludeTrailingPathDelimiter(FatherDir) + '/';
iFindResult := FindFirst(FatherDir + '*.*', faAnyFile , SearchRec);
while iFindResult = 0 do
begin
if SearchRec.Attr = faDirectory then //判断是否是目录
begin
if SearchRec.Name <> '.' AND SearchRec.Name <> '..' then
begin
Memo2.Lines.Add(FatherDir + SearchRec.Name);
WJMDB(FatherDir + SearchRec.Name);
end;
end
else
begin
Memo1.Lines.Add(FatherDir + SearchRec.Name);
end;
iFindResult := FindNext(SearchRec);
end;
FindClose(SearchRec);
end;
 
同意SmallGhost, 根目录没有. 和..
 
换个写法,大家看看可否,我测试通过了:
procedure TForm1.Button2Click(Sender: TObject);
var str1,str2:String;
aaa: WIN32_FIND_DATA;
han1:THandle;
begin
if OpenDialog1.Execute then
begin
han1:=FindFirstFile(PChar(ExtractFilePath(OpenDialog1.FileName)+'*.*'),aaa);
if han1<>INVALID_HANDLE_VALUE then
begin
repeat
str1:=aaa.cFileName;
str2:=aaa.cAlternateFileName;
{try
ChDir(str1);
Memo1.Lines.Add('目录:'+str1);
except
Memo1.Lines.Add(str1);
end;}
if ExtractFileExt(aaa.cFileName)='' then
Memo1.Lines.Add('目录:'+str1)
else
Memo1.Lines.Add(str1);
Memo2.Lines.Add(str2);
until
FindNextFile(han1,aaa)=False;
end;
end;
end;
 
问题解决了,Cyberphenix也是我的号,自己解决的我就不给大家分了,请见谅。
答案如下:
问题出在:if SearchRec.Attr = faDirectory then //判断是否是目录
这一句,很多目录,如在2k下NTFS格式C盘的WINNT目录,SearchRec.Attr返回值根本就不等于faDirectory(16),还有很多系统的目录都是返回各式各样的值,所以以上程序不能正确遍历含有特殊系统目录的目录。比较正确的答案如下(不能遍历系统压缩目录,如Winnt下的补丁生成的$********$目录):

procedure TForm1.WJMDB(FatherDir: String);
var
iFindResult: integer;
SearchRec: TSearchRec;

begin
FatherDir := ExcludeTrailingPathDelimiter(FatherDir) + '/';
iFindResult := FindFirst(FatherDir + '*.*', faAnyFile , SearchRec);

while iFindResult = 0 do
begin
if (SearchRec.Name = 'WINNT') then
Edit3.Text := inttostr(SearchRec.Attr);
if not((SearchRec.Name = '.') or (SearchRec.Name = '..')) then //not (wjmTime[1] in ['0'..'9'])
begin
if ((SearchRec.Attr = faDirectory) or (SearchRec.Attr = 8208)
or (SearchRec.Attr = 48) or (SearchRec.Attr = 8244) or (SearchRec.Attr = 20)
or (SearchRec.Attr = 17) or (SearchRec.Attr = 8241)
or (SearchRec.Attr = 8240)) then //判断是否是目录
begin
Memo2.Lines.Add(FatherDir + SearchRec.Name);
WJMDB(FatherDir + SearchRec.Name);
end
else
begin
Memo1.Lines.Add(FatherDir + SearchRec.Name);
end;
end;
iFindResult := FindNext(SearchRec);
end;
FindClose(SearchRec);
end;
 
忘了说还有浏览根目录时,第一个和第二个浏览的对象不是<.> <..>
 

Similar threads

S
回复
0
查看
916
SUNSTONE的Delphi笔记
S
S
回复
0
查看
895
SUNSTONE的Delphi笔记
S
S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
926
SUNSTONE的Delphi笔记
S
后退
顶部