近日没啥事情,研究了一下 everything、光速搜索原理。花了一个礼拜时间,终于搞定。

废话不多说,直接上代码:

[delphi] view plaincopy
  1. unit uMFTSearchFile;
  2. {
  3. dbyoung@sina.com
  4. 2018-04-23
  5. }
  6. interface
  7. uses Windows, System.Classes, Generics.Collections;
  8. { 获取磁盘所有文件列表 }
  9. function GetLogicalDiskAllFiles(const chrLogiclDiskName: Char; var FileList: TStringList; const bSort: Boolean = False): Boolean;
  10. implementation
  11. type
  12. PFileInfo = ^TFileInfo;
  13. TFileInfo = record
  14. strFileName: String;               // 文件名称
  15. FileReferenceNumber: UInt64;       // 文件的ID
  16. ParentFileReferenceNumber: UInt64; // 文件的父ID
  17. end;
  18. const
  19. PARTITION_IFS          = $07;
  20. BUF_LEN                = 500 * 1024;
  21. USN_DELETE_FLAG_DELETE = $00000001;
  22. c_UInt64Root           = 1407374883553285;
  23. type
  24. PARTITION_INFORMATION = record
  25. StartingOffset: LARGE_INTEGER;
  26. PartitionLength: LARGE_INTEGER;
  27. HiddenSectors: Cardinal;
  28. PartitionNumber: Cardinal;
  29. PartitionType: Byte;
  30. BootIndicator: Boolean;
  31. RecognizedPartition: Boolean;
  32. RewritePartition: Boolean;
  33. end;
  34. CREATE_USN_JOURNAL_DATA = record
  35. MaximumSize: UInt64;
  36. AllocationDelta: UInt64;
  37. end;
  38. USN_JOURNAL_DATA = record
  39. UsnJournalID: UInt64;
  40. FirstUsn: Int64;
  41. NextUsn: Int64;
  42. LowestValidUsn: Int64;
  43. MaxUsn: Int64;
  44. MaximumSize: UInt64;
  45. AllocationDelta: UInt64;
  46. end;
  47. MFT_ENUM_DATA = record
  48. StartFileReferenceNumber: UInt64;
  49. LowUsn: Int64;
  50. HighUsn: Int64;
  51. end;
  52. PUSN = ^USN;
  53. USN = record
  54. RecordLength: Cardinal;
  55. MajorVersion: Word;
  56. MinorVersion: Word;
  57. FileReferenceNumber: UInt64;
  58. ParentFileReferenceNumber: UInt64;
  59. USN: Int64;
  60. TimeStamp: LARGE_INTEGER;
  61. Reason: Cardinal;
  62. SourceInfo: Cardinal;
  63. SecurityId: Cardinal;
  64. FileAttributes: Cardinal;
  65. FileNameLength: Word;
  66. FileNameOffset: Word;
  67. FileName: PWideChar;
  68. end;
  69. DELETE_USN_JOURNAL_DATA = record
  70. UsnJournalID: UInt64;
  71. DeleteFlags: Cardinal;
  72. end;
  73. { TStringList 按数值排序 }
  74. function Int64Sort(List: TStringList; Index1, Index2: Integer): Integer;
  75. var
  76. Int64A, Int64B: Int64;
  77. begin
  78. Int64A := PFileInfo(List.Objects[Index1])^.FileReferenceNumber;
  79. Int64B := PFileInfo(List.Objects[Index2])^.FileReferenceNumber;
  80. if Int64A < Int64B then
  81. Result := -1
  82. else if Int64A = Int64B then
  83. Result := 0
  84. else
  85. Result := 1;
  86. end;
  87. { 简化的 MOVE 函数,也可以用 MOVE 函数来替代 }
  88. procedure MyMove(const Source; var Dest; Count: NativeInt); assembler;
  89. asm
  90. FILD    QWORD PTR [EAX]
  91. FISTP   QWORD PTR [EDX]
  92. end;
  93. { 获取文件全路径,包含路径和文件名 }
  94. procedure GetFullFileName(var FileList: TStringList; const chrLogiclDiskName: Char; const bSort: Boolean = False);
  95. var
  96. UInt64List: TArray<UInt64>;
  97. III       : Integer;
  98. UPID      : UInt64;
  99. intIndex  : Integer;
  100. begin
  101. { 将 FileList 按 FileReferenceNumber 数值排序 }
  102. FileList.Sorted := False;
  103. FileList.CustomSort(Int64Sort);
  104. { 将排序好的 FileReferenceNumber 复制到 UInt64 数组列表中,便于下面进行快速查找 <TArray.BinarySearch 为高效的折半查找> }
  105. SetLength(UInt64List, FileList.Count);
  106. for III := 0 to FileList.Count - 1 do
  107. begin
  108. UInt64List[III] := PFileInfo(FileList.Objects[III])^.FileReferenceNumber;
  109. end;
  110. { 获取每一个文件全路径名称 }
  111. for III := 0 to FileList.Count - 1 do
  112. begin
  113. UPID := PFileInfo(FileList.Objects[III])^.ParentFileReferenceNumber;
  114. while TArray.BinarySearch(UInt64List, UPID, intIndex) do
  115. begin
  116. UPID                  := PFileInfo(FileList.Objects[intIndex])^.ParentFileReferenceNumber;
  117. FileList.Strings[III] := PFileInfo(FileList.Objects[intIndex])^.strFileName + '\' + FileList.Strings[III];
  118. end;
  119. FileList.Strings[III] := (chrLogiclDiskName + ':\' + FileList.Strings[III]);
  120. end;
  121. { 将所有文件按文件名排序 }
  122. if bSort then
  123. FileList.Sort;
  124. end;
  125. { 获取磁盘所有文件列表 }
  126. function GetLogicalDiskAllFiles(const chrLogiclDiskName: Char; var FileList: TStringList; const bSort: Boolean = False): Boolean;
  127. var
  128. Info       : PARTITION_INFORMATION;
  129. bStatus    : Boolean;
  130. hRootHandle: THandle;
  131. hTempHandle: Cardinal;
  132. cujd       : CREATE_USN_JOURNAL_DATA;
  133. ujd        : USN_JOURNAL_DATA;
  134. med        : MFT_ENUM_DATA;
  135. dujd       : DELETE_USN_JOURNAL_DATA;
  136. dwRet      : DWORD;
  137. Buffer     : array [0 .. BUF_LEN - 1] of Char;
  138. UsnRecord  : PUSN;
  139. strFileName: String;
  140. int64Size  : Integer;
  141. pfi        : PFileInfo;
  142. III        : Integer;
  143. begin
  144. Result := False;
  145. { 打开磁盘 需要管理员权限 }
  146. hTempHandle := 0;
  147. hRootHandle := CreateFile(PChar('\\.\' + chrLogiclDiskName + ':'), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, hTempHandle);
  148. if hRootHandle = INVALID_HANDLE_VALUE then
  149. Exit;
  150. try
  151. { 是否是NTFS磁盘格式 }
  152. if not DeviceIoControl(hRootHandle, IOCTL_DISK_GET_PARTITION_INFO, nil, 0, @Info, Sizeof(Info), dwRet, nil) then
  153. Exit;
  154. if not Info.RecognizedPartition then
  155. Exit;
  156. if Info.PartitionType <> PARTITION_IFS then
  157. Exit;
  158. { 初始化USN日志文件 }
  159. bStatus := DeviceIoControl(hRootHandle, FSCTL_CREATE_USN_JOURNAL, @cujd, Sizeof(cujd), nil, 0, dwRet, nil);
  160. if not bStatus then
  161. Exit;
  162. { 获取USN日志基本信息 }
  163. bStatus := DeviceIoControl(hRootHandle, FSCTL_QUERY_USN_JOURNAL, nil, 0, @ujd, Sizeof(ujd), dwRet, nil);
  164. if not bStatus then
  165. Exit;
  166. { 枚举USN日志文件中的所有记录 }
  167. med.StartFileReferenceNumber := 0;
  168. med.LowUsn                   := 0;
  169. med.HighUsn                  := ujd.NextUsn;
  170. int64Size                    := Sizeof(Int64);
  171. while DeviceIoControl(hRootHandle, FSCTL_ENUM_USN_DATA, @med, Sizeof(med), @Buffer, BUF_LEN, dwRet, nil) do
  172. begin
  173. { 找到第一个 USN 记录 }
  174. UsnRecord := PUSN(Integer(@(Buffer)) + int64Size);
  175. while dwRet > 60 do
  176. begin
  177. { 获取文件名称 }
  178. strFileName := PWideChar(Integer(UsnRecord) + UsnRecord^.FileNameOffset);
  179. strFileName := Copy(strFileName, 1, UsnRecord^.FileNameLength div 2);
  180. { 将文件信息添加到列表中 }
  181. pfi                            := AllocMem(Sizeof(TFileInfo)); // 不要忘记释放内存
  182. pfi^.strFileName               := strFileName;
  183. pfi^.FileReferenceNumber       := UsnRecord^.FileReferenceNumber;
  184. pfi^.ParentFileReferenceNumber := UsnRecord^.ParentFileReferenceNumber;
  185. FileList.AddObject(strFileName, TObject(pfi));
  186. { 获取下一个 USN 记录 }
  187. if UsnRecord.RecordLength > 0 then
  188. Dec(dwRet, UsnRecord.RecordLength)
  189. else
  190. Break;
  191. UsnRecord := PUSN(Cardinal(UsnRecord) + UsnRecord.RecordLength);
  192. end;
  193. MyMove(Buffer, med, int64Size);
  194. end;
  195. { 获取文件全路径,包含路径和文件名 }
  196. GetFullFileName(FileList, chrLogiclDiskName, bSort);
  197. { 释放内存 }
  198. for III := 0 to FileList.Count - 1 do
  199. begin
  200. FreeMem(PFileInfo(FileList.Objects[III]));
  201. end;
  202. { 删除USN日志文件信息 }
  203. dujd.UsnJournalID := ujd.UsnJournalID;
  204. dujd.DeleteFlags  := USN_DELETE_FLAG_DELETE;
  205. DeviceIoControl(hRootHandle, FSCTL_DELETE_USN_JOURNAL, @dujd, Sizeof(dujd), nil, 0, dwRet, nil);
  206. finally
  207. CloseHandle(hRootHandle);
  208. end;
  209. end;
  210. end.

Delphi 10.2 环境下开发。

调用:

var FileList : TStringList;

begin

FileList     := TStringList.Create;

GetLogicalDiskAllFiles('C', FileList, False);

FileList.SaveToFile('d:\temp.txt', TEncoding.UTF8);

FileList.Free;

end;

在我的机器上100万个文件,耗时7秒左右。200万个文件,耗时15秒左右。

转载于:https://www.cnblogs.com/h2zZhou/p/9222619.html

[转载]Delphi 版 everything、光速搜索代码相关推荐

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

    Delphi 版 everything.光速搜索代码>,文章中关于获取文件全路径的函数:GetFullFileName,有一个地方值得优化. 就是有多个文件,它们可能属于同一个目录. 譬如 Sy ...

  2. Delphi 版 everything、光速搜索代码

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

  3. 《Delphi 版 everything、光速搜索代码》 关于获取文件全路径 GetFullFileName 函数的优化

    <Delphi 版 everything.光速搜索代码>,文章中关于获取文件全路径的函数:GetFullFileName,有一个地方值得优化. 就是有多个文件,它们可能属于同一个目录. 譬 ...

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

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

  5. WinAPI【远程注入】利用远程线程注入DLLDelphi版

    { WinAPI[远程注入]利用远程线程注入DLLDelphi版} (okwary) 小叹的学习园地 ( SDK文档里是这样描述的:进程是一个正在运行的程序,它拥有自己的地址空间,拥有自己的 ...

  6. PHP特级课视频教程_第二十八集 PHP搜索代码测试_李强强

    2019独角兽企业重金招聘Python工程师标准>>> 教程内容: 1.linux下网站开发 2.samba服务器网站共享 3.网站权限设计 4.php搜索代码测试 5.php中sp ...

  7. flash 版的mp3编码代码

    flash 版的mp3编码代码 Shine MP3 Encoder on Alchemy http://code.google.com/p/flash-kikko/ 简介 Shine简单轻量级的mp3 ...

  8. 用python编写一个高效搜索代码工具

    用python编写一个高效搜索代码工具 大多码农在linux环境下使用grep+关键词的命令搜索自己想要的代码或者log文件.今天介绍用python如何编写一个更强大的搜索工具,windows下也适用 ...

  9. 从内存中加载DLL Delphi版(转)

    源:从内存中加载DLL DELPHI版 原文 : http://www.2ccc.com/article.asp?articleid=5784 MemLibrary.pas //从内存中加载DLL D ...

最新文章

  1. SQL Server 文件和文件组
  2. 支持向量机SVM 参数选择
  3. python 内存回收机制_Python垃圾回收机制是什么
  4. hdu 1053 Entropy (哈夫曼树)
  5. DDoS deflate的安装使用
  6. 网络防火墙实战-基于pfsense(1)
  7. backbone源码之factory
  8. python程序员工资-Python工资高还是Java?
  9. mybatis驼峰映射
  10. 开心盒子助手3.0版|开心盒子助手工具3.0电脑版
  11. SQL注入(持续更新中)
  12. python 画图十大工具_Python画图工具matplotlib的使用(图形并茂)
  13. numpy.ones用法
  14. 学计算机编程难吗,电脑编程难学吗 如何才能学好电脑编程
  15. 华为服务器系列产品介绍,裸金属服务器产品介绍
  16. 2018年我跑去做淘宝了(续篇)
  17. 理解Spring Security中permitAll()和anonymous()的区别
  18. vue 自定义指令 directives
  19. Windows驱动学习第一步,第一个Windows驱动
  20. 【Codecs系列】X264码率控制总结1——ABR,CQP,CRF

热门文章

  1. 无线传感器网络复习(武昌首义学院)
  2. Adobe Illustrator CC(简称Al)里如何使用钢笔工具
  3. 致自己四年后的一封信
  4. 高质量的JAVA社区
  5. “《王者荣耀》游戏的无监督精彩片段检测”论文解读
  6. VICTS(可变倾角连续横向枝节)天线的封闭表达式
  7. 差速机器人的纯轨迹跟踪仿真(Matlab)
  8. 单招计算机面试技巧和注意事项,单招面试技巧和注意事项有哪些
  9. 三维空间:点到线的距离,点到面上的投影,直线在平面上的投影直线方程(平面束)
  10. Linux开发环境相关包的下载路径