首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >从零开始:如何用纯 C# 开发一款媲美 “Everything” 的文件搜索工具

从零开始:如何用纯 C# 开发一款媲美 “Everything” 的文件搜索工具

作者头像
独立观察员
发布2025-11-13 18:56:31
发布2025-11-13 18:56:31
1020
举报

众所周知,通过读取 USN 日志来搜索文件,比起传统的递归遍历文件夹,效率要高得多。但想要达到像 “Everything” 那样极致的速度,其实并不简单——哪怕只是几十毫秒的延迟,用户体验也可能天差地别。

如今,“Everything” 的界面风格略显经典,某些操作习惯也难以高度自定义。想必很多用户都希望有一款既能极致高效,又完全契合个人使用习惯的搜索工具:比如更灵活的快捷键、更丰富的右键菜单和后续操作联动等。正因如此,我决定重新开发这样一款工具,并将整个开发过程中的思路与遇到的“坑”记录下来。最终代码与实现已完全开源。

一、整体思路

整个项目可分为两大部分:数据处理UI 交互

数据处理流程

•a. 从磁盘缓存中读取文件信息•b. 将数据加载至内存•c. 执行字符串匹配•d. 返回匹配结果

UI 交互流程

•a. 响应用户输入•b. 触发搜索并获取结果•c. 更新界面显示

二、提升数据处理效率

a. 从磁盘缓存读取文件信息

我们通过读取 USN 日志获取文件信息。每条记录应至少包含:文件索引 ID(FileReferenceNumber, ulong)、父级索引 ID(ParentFileReferenceNumber, ulong)和文件名(含文件夹名称)。注意,USN 并不直接提供完整路径,我们需要根据父级索引逐级拼接出真实路径。

另一个关键是增量更新。USN 能记录文件状态变化(如创建、删除、重命名),通过监听如 USN_REASON_FILE_CREATE | USN_REASON_FILE_DELETE | USN_REASON_RENAME_NEW_NAME 这类事件,可实现高效的数据更新,远胜于传统的文件监控方式。

b. 内存中的搜索策略

最基础的搜索方式是遍历所有字符串,但这样性能远远不够。我尝试了以下方法:

建立索引机制:采用类似布隆过滤器的结构,使用 ulong 类型做初步筛选,通过预先的"或"运算初筛,实测可提升 2–3 倍搜索速度。

代码语言:javascript
复制
public static ulong TBS(string txt)
 {
     ulong indexValue=0;

     for (int i = 0; i < SCREENCHARNUM; i++)
     {        
         if (txt.Contains(alphbet[i], StringComparison.OrdinalIgnoreCase))
         {
             SetBit(ref indexValue, i);
         }
         else
         {
             ClearBit(ref indexValue, i);
         }
     }
     return indexValue;
 }

多线程搜索:将数据分组并用多线程并行处理。但在实际测试中(数据量 500W+),由于需频繁加锁同步结果,性能提升微乎其微,反而增加了代码复杂度。•拼音首字母支持:本项目加入了拼音首字母检索功能。由于实现较为直接,也带来了一定的匹配开销。如果去掉该功能,搜索速度还能进一步提升。

c. 返回结果的方式

搜索结果使用定长数组存储,每次搜索只顺序更新前若干条匹配结果的引用和总数量,几乎没有额外开销。


三、优化 UI 响应与渲染

UI 响应设计的重要性不亚于数据处理,甚至各占半壁江山。本项目先后尝试了 WinForms 和 Avalonia 两种 UI 框架,最终选择了支持 AOT 发布的 Avalonia,它在保持相近性能的同时,界面效果更现代。

响应用户输入与执行任务

我们将“用户输入”和“字符串匹配”分别放在不同线程中执行,通过异步信号机制触发或取消搜索任务,坚决避免阻塞 UI 线程。搜索任务运行在一个常驻循环中,避免因反复创建线程带来的开销。

高效更新 UI

面对海量数据的实时展示,虚拟化 UI 是必须的。

•在 WinForms 中,可使用 ListView 的虚拟模式动态生成条目。•在 Avalonia 中,我使用的是 ListBox 的虚拟化方案,并结合 ReactiveUI 框架,将 DataContext 绑定到一个可变长数据模型上。每次搜索结果更新时,通过 IEnumerable 接口延迟生成显示项,实现流畅渲染。

代码语言:javascript
复制
public class DataViewModel<T> : ReactiveObject
 {
     private IList<T> _allData = [];
     private IEnumerable<T> _displayedData = [];
     private int _displayCount = 100;

     public IEnumerable<T> DisplayedData
     {
         get => _displayedData;
         private set => this.RaiseAndSetIfChanged(ref _displayedData, value);
     }

     public int DisplayCount
     {
         get => _displayCount;
         set
         {
             _displayCount = value;
             UpdateDisplayedData();
         }
     }

     public DataViewModel()
     {
     }

     public void Bind(IList<T> _allData)
     {
         if (this._allData != _allData)
         {
             // 生成测试数据(实际中可能从文件或数据库加载)
             this._allData = _allData;
             UpdateDisplayedData();
         }
     }

     private void UpdateDisplayedData()
     {
         // 使用 LINQ 的 Take(),这是惰性求值的,性能很好
         DisplayedData = _allData.Take(DisplayCount);
     }

     // 快速切换到不同数量级
     public void SetDisplayCount(int count)
     {
         if (DisplayCount != count)
         {
             if (count < 0) count = 0;
             DisplayCount = count;
         }
     }

文件路径和图标的获取都是动态完成的(可适当引入缓存)。最初图标采用异步加载,但会出现闪烁现象,后来改为同步获取,效果反而更稳定。

代码语言:javascript
复制
        public string FileName => PathHelper.getfilePath(fileName).ToString();
        public string FilePath => PathHelper.GetPath(this).ToString();

四、额外功能

在此基础上,我们还实现了诸如全局热键、搜索历史记录、自定义右键菜单等扩展功能,进一步提升实用性和个性化程度。

五、结语

如果你对这款工具有任何建议或想法,欢迎随时交流!项目已在 GitHub 完全开源,如果你觉得有用,欢迎点个 Star ⭐️支持一下! https://github.com/LdotJdot/TDS[1]

References

[1]: https://github.com/LdotJdot/TDS

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-09-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 独立观察员博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、整体思路
  • 二、提升数据处理效率
    • a. 从磁盘缓存读取文件信息
    • b. 内存中的搜索策略
    • c. 返回结果的方式
  • 三、优化 UI 响应与渲染
    • 响应用户输入与执行任务
    • 高效更新 UI
  • 四、额外功能
  • 五、结语
    • References
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档