Everything是如何搜索的

写在前面

使用了Everything之后,一直对他的搜索速度感兴趣,在网上也看了很多对其原理的揭秘,终于有空找了个源码研究了一下,原理就是对NTFS的USN特性进行使用。

原理

详细解释我参照别人家的博客来一段:

当扇区的文件有变化时,操作系统会往USN Journal文件中追加一条记录,该记录包含文件名、变化发生的时间、变化的原因等信息,而不包含变化的内容。每一条记录用一个64位数字标识,称作USN(UpdateSequence Number)。微软用每一条记录在日志文件中的偏移作为该记录的USN,这样可以快速地通过USN获取到对应的记录。显而易见,USN是递增的,但是不连续。

所以如果想获得磁盘的文件只需要读取日志即可。

网上的源码有很多,关于读取日志,从日志转换成完整路径都不难理解,如果想自己写一个也是可以的。

问题

我认为需要考虑的主要问题:

  1. 从上次读取的位置继续读取;
  2. 新增或删除文件处理。

Everything 源码超级简述

源码仔细看并不难理解。
UsnOperator 类中,我认为比较重要的一点,是如何继续读取

public List<UsnEntry> GetEntries()
{
    var result = new List<UsnEntry>();
    UsnErrorCode usnErrorCode = this.QueryUSNJournal();
    if (usnErrorCode == UsnErrorCode.SUCCESS)
    {
        MFT_ENUM_DATA mftEnumData = new MFT_ENUM_DATA();
        mftEnumData.StartFileReferenceNumber = 0;

        // 如果想从上次的位置继续读取日志
        // 将lowUsn修改至上次最后一个UsnEntry.Usn即可
        mftEnumData.LowUsn = 0;
        mftEnumData.HighUsn = this.ntfsUsnJournalData.NextUsn;

        int sizeMftEnumData = Marshal.SizeOf(mftEnumData);
        IntPtr ptrMftEnumData = GetHeapGlobalPtr(sizeMftEnumData);
        Marshal.StructureToPtr(mftEnumData, ptrMftEnumData, true);

        int ptrDataSize = sizeof(UInt64) + 10000;
        IntPtr ptrData = GetHeapGlobalPtr(ptrDataSize);

        uint outBytesCount;

        while (false != Win32Api.DeviceIoControl(
            this.DriveRootHandle,
            UsnControlCode.FSCTL_ENUM_USN_DATA,
            ptrMftEnumData,
            sizeMftEnumData,
            ptrData,
            ptrDataSize,
            out outBytesCount,
            IntPtr.Zero))
        {

            IntPtr ptrUsnRecord = new IntPtr(ptrData.ToInt32() + sizeof(Int64));
            while (outBytesCount > 60)
            {
                var usnRecord = new USN_RECORD_V2(ptrUsnRecord);
                result.Add(new UsnEntry(usnRecord));
                ptrUsnRecord = new IntPtr(ptrUsnRecord.ToInt32() + usnRecord.RecordLength);
                outBytesCount -= usnRecord.RecordLength;
            }

            Marshal.WriteInt64(ptrMftEnumData, Marshal.ReadInt64(ptrData, 0));
        }

        Marshal.FreeHGlobal(ptrData);
        Marshal.FreeHGlobal(ptrMftEnumData);
    }
    return result;
}

使用 FileSystemWatcher 监听文件变化

关于电脑文件的修改监听,C#有相应的类来处理,非常方便,感兴趣可深挖:

FileSystemWatcher _watcher = new FileSystemWatcher(@"J:\", "*.*");
_watcher.Created += new FileSystemEventHandler(OnProcess);
_watcher.Changed += new FileSystemEventHandler(OnProcess);
_watcher.Deleted += new FileSystemEventHandler(OnProcess);
_watcher.Renamed += new RenamedEventHandler(OnFileRenamed);
_watcher.IncludeSubdirectories = true;
_watcher.EnableRaisingEvents = true;

下载

Everything相关资料下载

如果没有积分,也可以关注我获取哟~
hi

参考资料

DeviceIOControl详解-各个击破

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

于大大大洋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值