Delphi 版 everything、光速搜索代码》,文章中关于获取文件全路径的函数:GetFullFileName,有一个地方值得优化。

就是有多个文件,它们可能属于同一个目录。

譬如 System32 目录下有2000多个文件,GetFullFileName 还是进行了2000多次的查询,效率肯定是受影响的。

先处理目录,获取目录全路径名称。

然后文件只用查询一次,就知道它的父路径的全路径了。效率肯定会提高的。尝试了一下。

  1. { 获取文件全路径,包含路径和文件名 }
  2. procedure GetFullFileName(var FileList: TStringList; const chrLogiclDiskName: Char; const bSort: Boolean = False);
  3. var
  4. UInt64DirList    : TArray<UInt64>;
  5. III              : Integer;
  6. UPID             : UInt64;
  7. intIndex         : Integer;
  8. dirList          : TStringList;
  9. intDirectoryCount: Integer;
  10. begin
  11. { 将 FileList 按 FileReferenceNumber 数值排序 }
  12. FileList.Sorted := False;
  13. FileList.CustomSort(Int64Sort);
  14. { 先处理目录,获取路径的全路径名称 }
  15. dirList := TStringList.Create;
  16. try
  17. { 获取目录的总数 }
  18. intDirectoryCount := 0;
  19. for III           := 0 to FileList.Count - 1 do
  20. begin
  21. if PFileInfo(FileList.Objects[III])^.bDirectory then
  22. begin
  23. Inc(intDirectoryCount);
  24. end;
  25. end;
  26. SetLength(UInt64DirList, intDirectoryCount);
  27. { 将所有目录信息添加到目录列表 }
  28. intDirectoryCount := 0;
  29. for III           := 0 to FileList.Count - 1 do
  30. begin
  31. if PFileInfo(FileList.Objects[III])^.bDirectory then
  32. begin
  33. dirList.AddObject(PFileInfo(FileList.Objects[III])^.strFileName, FileList.Objects[III]);
  34. UInt64DirList[intDirectoryCount] := PFileInfo(FileList.Objects[III])^.FileReferenceNumber;
  35. Inc(intDirectoryCount);
  36. end;
  37. end;
  38. { 获取目录的全路径名称 }
  39. intDirectoryCount := 0;
  40. for III           := 0 to FileList.Count - 1 do
  41. begin
  42. if PFileInfo(FileList.Objects[III])^.bDirectory then
  43. begin
  44. UPID := PFileInfo(FileList.Objects[III])^.ParentFileReferenceNumber;
  45. while TArray.BinarySearch(UInt64DirList, UPID, intIndex) do
  46. begin
  47. UPID                  := PFileInfo(dirList.Objects[intIndex])^.ParentFileReferenceNumber;
  48. FileList.Strings[III] := PFileInfo(dirList.Objects[intIndex])^.strFileName + '\' + FileList.Strings[III];
  49. end;
  50. FileList.Strings[III]              := (chrLogiclDiskName + ':\' + FileList.Strings[III]);
  51. dirList.Strings[intDirectoryCount] := FileList.Strings[III];
  52. Inc(intDirectoryCount);
  53. end;
  54. end;
  55. { 再获取每个文件的全路径 }
  56. for III := 0 to FileList.Count - 1 do
  57. begin
  58. if not PFileInfo(FileList.Objects[III])^.bDirectory then
  59. begin
  60. UPID := PFileInfo(FileList.Objects[III])^.ParentFileReferenceNumber;
  61. if TArray.BinarySearch(UInt64DirList, UPID, intIndex) then
  62. begin
  63. FileList.Strings[III] := dirList.Strings[intIndex] + '\' + FileList.Strings[III];
  64. end
  65. else
  66. begin
  67. FileList.Strings[III] := chrLogiclDiskName + '\' + FileList.Strings[III];
  68. end;
  69. end;
  70. end;
  71. { 将所有文件按文件名排序 }
  72. if bSort then
  73. FileList.Sort;
  74. finally
  75. dirList.Free;
  76. end;
  77. end;

这个函数比原来的函数效率上刚好提高了一倍。

100万个的文件,耗时4秒左右。200万个的文件,耗时8秒左右。

注:原有的  TFileInfo 添加个目录属性:

TFileInfo = record
    strFileName: String;               // 文件名称
    bDirectory: Boolean;               // 是否是目录 <增加>
    FileReferenceNumber: UInt64;       // 文件的ID
    ParentFileReferenceNumber: UInt64; // 文件的父ID

end;

在代码

FileList.AddObject(strFileName, TObject(pfi));

前,添加一行:

pfi^.bDirectory  := UsnRecord^.FileAttributes and FILE_ATTRIBUTE_DIRECTORY = FILE_ATTRIBUTE_DIRECTORY;

[转载]《Delphi 版 everything、光速搜索代码》 关于获取文件全路径 GetFullFileName 函数的优化的更多相关文章

  1. [转载]Delphi 版 everything、光速搜索代码

    近日没啥事情,研究了一下 everything.光速搜索原理.花了一个礼拜时间,终于搞定. 废话不多说,直接上代码: unit uMFTSearchFile; { dbyoung@sina.com 2 ...

  2. Delphi获取文件名、文件名不带扩展名、文件名的方法;delphi 获取文件所在路径

    取文件名 ExtractFileName(FileName); 取文件扩展名: ExtractFileExt(filename); 取文件名,不带扩展名: 方法一:   Function Extrac ...

  3. java版ftp简易客户端(可以获取文件的名称及文件大小)

    java版ftp简易客户端(可以获取文件的名称及文件大小) package com.ccb.ftp; import java.io.IOException; import java.net.Socke ...

  4. 教程-Delphi中的GExperts搜索代码快捷键

    Shift+Ait+S  打开搜索 Ctrl+Ait+R 打开上次搜索结果

  5. delphi根据进程PID获取程序所在路径的函数(用OpenProcess取得句柄,用GetModuleFileNameEx取得程序名)

    uses psapi; {根据进程PID获取程序所在路径的函数}function GetProcessExePath(PID: Cardinal): string;varpHandle: THandl ...

  6. 拖放获取文件信息的bat代码

    参考:岁月如歌-通过拖曳获取文件信息的bat代码 拖放获取文件信息的bat代码 使用命令行配合7z解压文件时由于每次解压的文件不同,因此搜索了一下拖放识别文件信息的方法,以此方式来减轻工作量 获取文件 ...

  7. Delphi获取文件名、不带扩展名文件名、文件所在路径、上级文件夹路径的方法

    1.获取不带扩展名的文件名方法,利用ChangeFileExt函数修改传入参数的扩展为空,并不会对文件本身产生变更. ChangeFileExt(ExtractFileName('D:\KK\Test ...

  8. 通过崩溃地址找错误行数之Delphi版

    通过崩溃地址找错误行数之Delphi版2009-5-11 17:42:35 来源: 转载 作者:网络 访问:360 次 被顶:2 次 字号:[大 中 小]核心提示:什么是 MAP 文件?简单地讲, M ...

  9. 雪花算法(snowflake)delphi版

    雪花算法简单描述: + 最高位是符号位,始终为0,不可用. + 41位的时间序列,精确到毫秒级,41位的长度可以使用69年.时间位还有一个很重要的作用是可以根据时间进行排序. + 10位的机器标识,1 ...

随机推荐

  1. centos安装更新Python2.7以及pip的安装

    一.首先对相关的软件进行更新 python -V yum -y update yum groupinstall -y development yum install -y zlib zlib-dev ...

  2. C++ cin.ignore()用法

    cin.ignore(int a,char b); a为一行中最大读取字符长度,b为某一个字符.在缓冲区中寻找b,找到后忽略b以前的所有字符(包括b).如果在a的范围内还没有找到b,则忽略b以前的所有 ...

  3. centos7.5英文环境切换到中文环境,再切回中文环境后 ,terminal不能用

    1.查看系统日志 less /var/logs/message May 12 21:54:41 localhost python: SELinux is preventing /usr/libexec ...

  4. 《深入理解Android2》读书笔记(二)

    接之前那篇<深入理解Android2>读书笔记(一) 下面几篇来分别详细分析 Binder类作为服务端的Bn的代表,BinderProxy类作为客户端的Bp的代表,BinderIntern ...

  5. 洛谷P1280 尼克的任务 [DP补完计划]

    题目传送门 题目描述 尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成. 尼克的一个工作日为N分钟,从 ...

  6. IoC控制反转和DI依赖注入

    控制反转(Inversion of Control,英文缩写为IoC)是框架的重要特征,并非面向对象编程的专用术语.它与依赖注入(Dependency           Injection,简称DI ...

  7. Oracle基础了解

    数据库: 关系型数据库 select * from 表名 非关系型数据库(做不到复杂查询) 以对象的形式进行存储 {"aaa":"ccc"}---键值对 ora ...

  8. 深度学习应用系列(三)| autokeras使用入门

    我们在构建自己的神经网络模型时,往往会基于预编译模型上进行迁移学习.但不同的训练数据.不同的场景下,各个模型表现不一,需要投入大量的精力进行调参,耗费相当多的时间才能得到自己满意的模型. 而谷歌近期推 ...

  9. Loj#6433「PKUSC2018」最大前缀和(状态压缩DP)

    题面 Loj 题解 先转化题意,其实这题在乘了\(n!\)以后就变成了全排列中的最大前缀和的和(有点拗口).\(n\leq20\),考虑状压\(DP\) 考虑一个最大前缀和\(\sum\limits_ ...

  10. 28、Flask实战第28天:cms后台模板渲染

    这节开始,我们需要用到前端模板.^_^..如果需要模板素材的同学,可以点击博客的右侧二维码进行打赏(10元),截图发送到邮箱463951510@qq.com,写明索取flask论坛素材即可,博主收到邮 ...