[转载]Delphi 版 everything、光速搜索代码
近日没啥事情,研究了一下 everything、光速搜索原理。花了一个礼拜时间,终于搞定。
废话不多说,直接上代码:
- unit uMFTSearchFile;
- {
- dbyoung@sina.com
- 2018-04-23
- }
- interface
- uses Windows, System.Classes, Generics.Collections;
- { 获取磁盘所有文件列表 }
- function GetLogicalDiskAllFiles(const chrLogiclDiskName: Char; var FileList: TStringList; const bSort: Boolean = False): Boolean;
- implementation
- type
- PFileInfo = ^TFileInfo;
- TFileInfo = record
- strFileName: String; // 文件名称
- FileReferenceNumber: UInt64; // 文件的ID
- ParentFileReferenceNumber: UInt64; // 文件的父ID
- end;
- const
- PARTITION_IFS = $07;
- BUF_LEN = 500 * 1024;
- USN_DELETE_FLAG_DELETE = $00000001;
- c_UInt64Root = 1407374883553285;
- type
- PARTITION_INFORMATION = record
- StartingOffset: LARGE_INTEGER;
- PartitionLength: LARGE_INTEGER;
- HiddenSectors: Cardinal;
- PartitionNumber: Cardinal;
- PartitionType: Byte;
- BootIndicator: Boolean;
- RecognizedPartition: Boolean;
- RewritePartition: Boolean;
- end;
- CREATE_USN_JOURNAL_DATA = record
- MaximumSize: UInt64;
- AllocationDelta: UInt64;
- end;
- USN_JOURNAL_DATA = record
- UsnJournalID: UInt64;
- FirstUsn: Int64;
- NextUsn: Int64;
- LowestValidUsn: Int64;
- MaxUsn: Int64;
- MaximumSize: UInt64;
- AllocationDelta: UInt64;
- end;
- MFT_ENUM_DATA = record
- StartFileReferenceNumber: UInt64;
- LowUsn: Int64;
- HighUsn: Int64;
- end;
- PUSN = ^USN;
- USN = record
- RecordLength: Cardinal;
- MajorVersion: Word;
- MinorVersion: Word;
- FileReferenceNumber: UInt64;
- ParentFileReferenceNumber: UInt64;
- USN: Int64;
- TimeStamp: LARGE_INTEGER;
- Reason: Cardinal;
- SourceInfo: Cardinal;
- SecurityId: Cardinal;
- FileAttributes: Cardinal;
- FileNameLength: Word;
- FileNameOffset: Word;
- FileName: PWideChar;
- end;
- DELETE_USN_JOURNAL_DATA = record
- UsnJournalID: UInt64;
- DeleteFlags: Cardinal;
- end;
- { TStringList 按数值排序 }
- function Int64Sort(List: TStringList; Index1, Index2: Integer): Integer;
- var
- Int64A, Int64B: Int64;
- begin
- Int64A := PFileInfo(List.Objects[Index1])^.FileReferenceNumber;
- Int64B := PFileInfo(List.Objects[Index2])^.FileReferenceNumber;
- if Int64A < Int64B then
- Result := -1
- else if Int64A = Int64B then
- Result := 0
- else
- Result := 1;
- end;
- { 简化的 MOVE 函数,也可以用 MOVE 函数来替代 }
- procedure MyMove(const Source; var Dest; Count: NativeInt); assembler;
- asm
- FILD QWORD PTR [EAX]
- FISTP QWORD PTR [EDX]
- end;
- { 获取文件全路径,包含路径和文件名 }
- procedure GetFullFileName(var FileList: TStringList; const chrLogiclDiskName: Char; const bSort: Boolean = False);
- var
- UInt64List: TArray<UInt64>;
- III : Integer;
- UPID : UInt64;
- intIndex : Integer;
- begin
- { 将 FileList 按 FileReferenceNumber 数值排序 }
- FileList.Sorted := False;
- FileList.CustomSort(Int64Sort);
- { 将排序好的 FileReferenceNumber 复制到 UInt64 数组列表中,便于下面进行快速查找 <TArray.BinarySearch 为高效的折半查找> }
- SetLength(UInt64List, FileList.Count);
- for III := 0 to FileList.Count - 1 do
- begin
- UInt64List[III] := PFileInfo(FileList.Objects[III])^.FileReferenceNumber;
- end;
- { 获取每一个文件全路径名称 }
- for III := 0 to FileList.Count - 1 do
- begin
- UPID := PFileInfo(FileList.Objects[III])^.ParentFileReferenceNumber;
- while TArray.BinarySearch(UInt64List, UPID, intIndex) do
- begin
- UPID := PFileInfo(FileList.Objects[intIndex])^.ParentFileReferenceNumber;
- FileList.Strings[III] := PFileInfo(FileList.Objects[intIndex])^.strFileName + '\' + FileList.Strings[III];
- end;
- FileList.Strings[III] := (chrLogiclDiskName + ':\' + FileList.Strings[III]);
- end;
- { 将所有文件按文件名排序 }
- if bSort then
- FileList.Sort;
- end;
- { 获取磁盘所有文件列表 }
- function GetLogicalDiskAllFiles(const chrLogiclDiskName: Char; var FileList: TStringList; const bSort: Boolean = False): Boolean;
- var
- Info : PARTITION_INFORMATION;
- bStatus : Boolean;
- hRootHandle: THandle;
- hTempHandle: Cardinal;
- cujd : CREATE_USN_JOURNAL_DATA;
- ujd : USN_JOURNAL_DATA;
- med : MFT_ENUM_DATA;
- dujd : DELETE_USN_JOURNAL_DATA;
- dwRet : DWORD;
- Buffer : array [0 .. BUF_LEN - 1] of Char;
- UsnRecord : PUSN;
- strFileName: String;
- int64Size : Integer;
- pfi : PFileInfo;
- III : Integer;
- begin
- Result := False;
- { 打开磁盘 需要管理员权限 }
- hTempHandle := 0;
- hRootHandle := CreateFile(PChar('\\.\' + chrLogiclDiskName + ':'), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, hTempHandle);
- if hRootHandle = INVALID_HANDLE_VALUE then
- Exit;
- try
- { 是否是NTFS磁盘格式 }
- if not DeviceIoControl(hRootHandle, IOCTL_DISK_GET_PARTITION_INFO, nil, 0, @Info, Sizeof(Info), dwRet, nil) then
- Exit;
- if not Info.RecognizedPartition then
- Exit;
- if Info.PartitionType <> PARTITION_IFS then
- Exit;
- { 初始化USN日志文件 }
- bStatus := DeviceIoControl(hRootHandle, FSCTL_CREATE_USN_JOURNAL, @cujd, Sizeof(cujd), nil, 0, dwRet, nil);
- if not bStatus then
- Exit;
- { 获取USN日志基本信息 }
- bStatus := DeviceIoControl(hRootHandle, FSCTL_QUERY_USN_JOURNAL, nil, 0, @ujd, Sizeof(ujd), dwRet, nil);
- if not bStatus then
- Exit;
- { 枚举USN日志文件中的所有记录 }
- med.StartFileReferenceNumber := 0;
- med.LowUsn := 0;
- med.HighUsn := ujd.NextUsn;
- int64Size := Sizeof(Int64);
- while DeviceIoControl(hRootHandle, FSCTL_ENUM_USN_DATA, @med, Sizeof(med), @Buffer, BUF_LEN, dwRet, nil) do
- begin
- { 找到第一个 USN 记录 }
- UsnRecord := PUSN(Integer(@(Buffer)) + int64Size);
- while dwRet > 60 do
- begin
- { 获取文件名称 }
- strFileName := PWideChar(Integer(UsnRecord) + UsnRecord^.FileNameOffset);
- strFileName := Copy(strFileName, 1, UsnRecord^.FileNameLength div 2);
- { 将文件信息添加到列表中 }
- pfi := AllocMem(Sizeof(TFileInfo)); // 不要忘记释放内存
- pfi^.strFileName := strFileName;
- pfi^.FileReferenceNumber := UsnRecord^.FileReferenceNumber;
- pfi^.ParentFileReferenceNumber := UsnRecord^.ParentFileReferenceNumber;
- FileList.AddObject(strFileName, TObject(pfi));
- { 获取下一个 USN 记录 }
- if UsnRecord.RecordLength > 0 then
- Dec(dwRet, UsnRecord.RecordLength)
- else
- Break;
- UsnRecord := PUSN(Cardinal(UsnRecord) + UsnRecord.RecordLength);
- end;
- MyMove(Buffer, med, int64Size);
- end;
- { 获取文件全路径,包含路径和文件名 }
- GetFullFileName(FileList, chrLogiclDiskName, bSort);
- { 释放内存 }
- for III := 0 to FileList.Count - 1 do
- begin
- FreeMem(PFileInfo(FileList.Objects[III]));
- end;
- { 删除USN日志文件信息 }
- dujd.UsnJournalID := ujd.UsnJournalID;
- dujd.DeleteFlags := USN_DELETE_FLAG_DELETE;
- DeviceIoControl(hRootHandle, FSCTL_DELETE_USN_JOURNAL, @dujd, Sizeof(dujd), nil, 0, dwRet, nil);
- finally
- CloseHandle(hRootHandle);
- end;
- end;
- 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、光速搜索代码相关推荐
- [转载]《Delphi 版 everything、光速搜索代码》 关于获取文件全路径 GetFullFileName 函数的优化...
Delphi 版 everything.光速搜索代码>,文章中关于获取文件全路径的函数:GetFullFileName,有一个地方值得优化. 就是有多个文件,它们可能属于同一个目录. 譬如 Sy ...
- Delphi 版 everything、光速搜索代码
近日没啥事情,研究了一下 everything.光速搜索原理.花了一个礼拜时间,终于搞定. 废话不多说,直接上代码: unit uMFTSearchFile; {dbyoung@sina.com201 ...
- 《Delphi 版 everything、光速搜索代码》 关于获取文件全路径 GetFullFileName 函数的优化
<Delphi 版 everything.光速搜索代码>,文章中关于获取文件全路径的函数:GetFullFileName,有一个地方值得优化. 就是有多个文件,它们可能属于同一个目录. 譬 ...
- 通过崩溃地址找错误行数之Delphi版
通过崩溃地址找错误行数之Delphi版 2009-5-11 17:42:35 来源: 转载 作者:网络 访问:360 次 被顶:2 次 字号:[大 中 小] 核心提示:什么是 MAP 文件?简单地讲, ...
- WinAPI【远程注入】利用远程线程注入DLLDelphi版
{ WinAPI[远程注入]利用远程线程注入DLLDelphi版} (okwary) 小叹的学习园地 ( SDK文档里是这样描述的:进程是一个正在运行的程序,它拥有自己的地址空间,拥有自己的 ...
- PHP特级课视频教程_第二十八集 PHP搜索代码测试_李强强
2019独角兽企业重金招聘Python工程师标准>>> 教程内容: 1.linux下网站开发 2.samba服务器网站共享 3.网站权限设计 4.php搜索代码测试 5.php中sp ...
- flash 版的mp3编码代码
flash 版的mp3编码代码 Shine MP3 Encoder on Alchemy http://code.google.com/p/flash-kikko/ 简介 Shine简单轻量级的mp3 ...
- 用python编写一个高效搜索代码工具
用python编写一个高效搜索代码工具 大多码农在linux环境下使用grep+关键词的命令搜索自己想要的代码或者log文件.今天介绍用python如何编写一个更强大的搜索工具,windows下也适用 ...
- 从内存中加载DLL Delphi版(转)
源:从内存中加载DLL DELPHI版 原文 : http://www.2ccc.com/article.asp?articleid=5784 MemLibrary.pas //从内存中加载DLL D ...
最新文章
- PyTorch入门学习(二):Autogard之自动求梯度
- 【视频课】一课彻底掌握深度学习人脸图像算法,长期更新
- bbs php redis,LAMP+redis搭建discuz论坛
- ospf工作原理_OSPF动态路由配置经典案例
- 事物与持久化_跟面试官侃半小时MySQL事务,说完原子性、一致性、持久性的实现...
- 拳王虚拟项目公社:利用减肥健身类虚拟资源项目,如何打造一套赚钱系统?
- 2021-04-25
- 串口数据接收、发送与USB转串口驱动下载
- 李笑来《自学是门手艺》经典语录
- 云解析 dns 服务器,你知道为什么云解析DNS又快又安全吗?
- Java学习笔记(24)——正则表达式
- 毕业设计c语言课程设计,大学毕业设计论文-—c语言课程设计.doc
- 基于MATLAB/Simulink的电力电子电路仿真技术——三相电流滞环跟踪逆变器
- 头歌:《C语言程序设计编程实践任务》教学团队:祁文青:选择结构程序设计
- 计算机财务管理系统基础知识,计算机财务管理实习报告
- NBS云硬盘无法挂载
- 微信多群直播机器人平台(一起学堂)
- cpp实现直线的DDA算法
- [实战分析] 编写高效的JavaScript程序
- 计算机四级网络技术题库套,全国计算机等级考试四级计算机网络第6套试题(3)...
热门文章
- 计算机仿真模拟软件心得,【仿真软件在计算机组装课中的应用】 计算机组装总结及心得...
- shell里面的PATH
- electron实现屏幕截图
- 【逻辑题】三个日本人
- 驰骋工作流引擎下载与安装步骤
- linux添加虚拟内存
- linux 时间与定时器编程原理,浅析 Linux 中的时间编程和实现原理-嵌入式-火龙果软件工程...
- 关于Linux下.bin格式文件的安装
- 如何查询软件著作权登记证书信息?软著登记证书查询网址?
- JAVA CRC-16(CRC-16/IBM)计算校验值