捐赠 | 广告 | 注册 | 发布 | 上传 | 关于我们    
  沪ICP备05001939号 DELPHI盒子 | 盒子论坛 | 盒子文章 | 盒子问答悬赏 | 最新更新 | 论坛检索 | 下载中心 | 高级搜索    
  精品专区 | 繁體中文 | 奖励公告栏 | 直通车账号登陆 | 关闭GOOGLE广告 | 临时留言    
 
广告
评论:演示两种方法来遍历文件
jackalan 26754 2006/10/23 12:48:04
多线程内慎用,资源消耗比较大。
cenjoy 26421 2006/10/4 18:18:00
你这种方法好是好,但是我最担心的是内存够不够用的问题!!!
aizaixiiii 26356 2006/9/29 10:28:32
hao!
monkey_cn 26048 2006/9/13 20:07:57
更实用点的封装:
{用队列的方法遍历文件
  path:=DriveComboBox1.Drive + ':';
  count:=EnumFileInQueue(StrNew(PChar(path)),Memo1.Lines);
}
function EnumFileInQueue(path: PChar;vFileList:TStrings): Longint; stdcall;
var
  searchRec: TSearchRec;
  found: Integer;
  tmpStr: string;
  curDir: string;
  dirs: TQueue;
  pszDir: PChar;
begin
  vFileList.Clear;
  Result := 0; //查找结果(文件数)
  dirs := TQueue.Create; //创建目录队列
  dirs.Push(path); //将起始搜索路径入队
  pszDir := dirs.Pop;
  curDir := StrPas(pszDir); //出队
  StrDispose(pszDir);

  while (True) do//开始遍历,直至队列为空
  begin
    tmpStr := curDir + '\*.*';//加上搜索后缀,得到类似'c:\*.*' 、'c:\windows\*.*'的搜索路径

    found := FindFirst(tmpStr, faAnyFile, searchRec);//在当前目录查找第一个文件、子目录
    while found = 0 do
    begin
      if (searchRec.Attr and faDirectory) <> 0 then//如果找到的是个目录
      begin
        if (searchRec.Name <> '.') and (searchRec.Name <> '..') then
        begin
          tmpStr := curDir + '\' + searchRec.Name;
          dirs.Push(StrNew(PChar(tmpStr)));
        end;
      end else
      begin
        Result := Result + 1;
        vFileList.Add(curDir + '\' + searchRec.Name);
      end;
      found := FindNext(searchRec);//查找下一个文件或目录
    end;
    if dirs.Count > 0 then
    begin
      pszDir := dirs.Pop;
      curDir := StrPas(pszDir);
      StrDispose(pszDir);
    end
    else
      break;
  end;

  //释放资源
  dirs.Free;
  FindClose(searchRec);
end;

{用递归的方法遍历文件}
function EnumFileInRecursion(path: PChar;vFileList:TStrings): Longint; stdcall;
var
  searchRec: TSearchRec;
  found: Integer;
  tmpStr: string;
begin
  vFileList.Clear;
  Result := 0; //查找结果(文件数)

  tmpStr := StrPas(path) + '\*.*';

  found := FindFirst(tmpStr, faAnyFile, searchRec);//第一个文件或目录
  while found = 0 do
  begin
    if (searchRec.Attr and faDirectory) <> 0 then
    begin
      if (searchRec.Name <> '.') and (searchRec.Name <> '..') then
      begin
        tmpStr := StrPas(path) + '\' + searchRec.Name;
        Result := Result + EnumFileInRecursion(PChar(tmpStr),vFileList);//递归调用
      end;
    end
    else begin
      Result := Result + 1;
      //把找到的文件加到Memo控件
      vFileList.Add(StrPas(path) + '\' + searchRec.Name);
    end;
    //查找下一个文件或目录
    found := FindNext(searchRec);
  end;
  //释放资源
  FindClose(searchRec);
end;
cenjoy 25884 2006/9/5 17:40:23
很感谢speedbin还给我发了邮件纠正了内存泄露的问题.
cenjoy 25883 2006/9/5 17:39:22
我的意思就是目录深度过长的问题.
"子目录",目录的子目录,子目录的子目录....
iamdream 25810 2006/9/1 22:48:00
楼主对递归的说法有问题吧?就算子目录非常多,只要它的目录深度不是太多,就不会导致堆栈溢出的!
我不知道楼主是自己使用递归遍历目录及文件遇到过堆栈溢出,还是听别人说的?
speedbin 25637 2006/8/24 19:21:50
楼主的代码存在严重的内存泄漏问题,光是StrNew分配内存,却没有使用StrDispose释放内存。我修改了一下代码,用FastMM检查没有内存泄漏报警,修改后的代码如下:

{用队列的方法遍历文件}
function EnumFileInQueue(path:PChar):Longint;stdcall;
var
    searchRec:TSearchRec;
    found:Integer;
    tmpStr:String;
    curDir:string;
    dirs:TQueue;
    pszDir: PChar;
begin
    Result:=0;//查找结果(文件数)
    dirs:=TQueue.Create;//创建目录队列
    dirs.Push(path);//将起始搜索路径入队
    pszDir := dirs.Pop;
    curDir:=StrPas(pszDir);//出队
    StrDispose(pszDir);
    {开始遍历,直至队列为空(即没有目录需要遍历)}
    while (True) do
    begin
        //加上搜索后缀,得到类似'c:\*.*' 、'c:\windows\*.*'的搜索路径
        tmpStr:=curDir+'\*.*';
        //在当前目录查找第一个文件、子目录
        found:=FindFirst(tmpStr,faAnyFile,searchRec);
        while found=0 do
        //找到了一个文件或目录后
        begin
          //如果找到的是个目录
          if (searchRec.Attr and faDirectory)<>0 then
          begin
          {在搜索非根目录(C:\、D:\)下的子目录时会出现'.','..'的"虚拟目录"
          大概是表示上层目录和下层目录吧。。。要过滤掉才可以}
          if (searchRec.Name <> '.') and (searchRec.Name <> '..') then
          begin
          {由于查找到的子目录只有个目录名,所以要添上上层目录的路径
          searchRec.Name = 'Windows';
          tmpStr:='c:\Windows';
          加个断点就一清二楚了
          }
          tmpStr:=curDir+'\'+searchRec.Name;
          {将搜索到的目录入队。让它先晾着。
          因为TQueue里面的数据只能是指针,所以要把string转换为PChar
          同时使用StrNew函数重新申请一个空间存入数据,否则会使已经进
          入队列的指针指向不存在或不正确的数据(tmpStr是局部变量)。}
          dirs.Push(StrNew(PChar(tmpStr)));
          end;
          end
          //如果找到的是个文件
          else begin
          {Result记录着搜索到的文件数。可是我是用CreateThread创建线程
          来调用函数的,不知道怎么得到这个返回值。。。我不想用全局变量}
          Result:=Result+1;
          //把找到的文件加到Memo控件
          Form1.Memo1.Lines.Add(curDir+'\'+searchRec.Name);
          end;
          //查找下一个文件或目录
          found:=FindNext(searchRec);
        end;
        {当前目录找到后,如果队列中没有数据,则表示全部找到了;
        否则就是还有子目录未查找,取一个出来继续查找。}
        if dirs.Count > 0 then
        begin
          pszDir := dirs.Pop;
          curDir:=StrPas(pszDir);
          StrDispose(pszDir);
        end
        else
          break;
    end;
    //释放资源
    dirs.Free;
    FindClose(searchRec);
end;
whb1573 25627 2006/8/24 11:26:03
哪个更快捷一些?
ccdos 25608 2006/8/23 16:16:29
太好了
学习中
第一页 上一页 下一页 最后页 有 10 条纪录 共1页 1 - 10
 用户名:
 密 码:
自动登陆(30天有效)
 
  DELPHI盒子版权所有 1999-2023 V4.01 粤ICP备10103342号-1 更新RSS列表