C# 快速搜索磁盘文件解决方案

高性能的 C# 文件搜索工具,使用多线程和异步 IO 技术实现快速磁盘文件搜索,支持通配符匹配、大小过滤、日期过滤等高级功能。

代码

1. 主窗体代码 (MainForm.cs)

csharp 复制代码
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;

namespace FastFileSearch
{
    public partial class MainForm : Form
    {
        private readonly ConcurrentBag<string> searchResults = new ConcurrentBag<string>();
        private CancellationTokenSource cancellationTokenSource;
        private readonly Stopwatch searchStopwatch = new Stopwatch();
        private int filesScanned;
        private long totalBytesScanned;

        public MainForm()
        {
            InitializeComponent();
            InitializeUI();
            LoadRecentSearches();
        }

        private void InitializeUI()
        {
            // 窗体设置
            this.Text = "闪电文件搜索工具";
            this.Size = new Size(900, 650);
            this.StartPosition = FormStartPosition.CenterScreen;
            this.BackColor = Color.FromArgb(240, 243, 249);
            this.Font = new Font("Segoe UI", 9);

            // 创建控件
            int yPos = 20;
            int labelWidth = 120;
            int controlWidth = 300;
            int rowHeight = 35;

            // 搜索路径
            lblPath = new Label { Text = "搜索路径:", Location = new Point(20, yPos), Size = new Size(labelWidth, 20), TextAlign = ContentAlignment.MiddleRight };
            txtPath = new TextBox { Location = new Point(150, yPos), Size = new Size(controlWidth, 25), Text = @"C:\" };
            btnBrowse = new Button { Text = "浏览...", Location = new Point(460, yPos), Size = new Size(75, 25), BackColor = Color.SteelBlue, ForeColor = Color.White, FlatStyle = FlatStyle.Flat };
            btnBrowse.FlatAppearance.BorderSize = 0;
            btnBrowse.Click += BtnBrowse_Click;

            // 文件名模式
            yPos += rowHeight;
            lblPattern = new Label { Text = "文件名模式:", Location = new Point(20, yPos), Size = new Size(labelWidth, 20), TextAlign = ContentAlignment.MiddleRight };
            txtPattern = new TextBox { Location = new Point(150, yPos), Size = new Size(controlWidth, 25), Text = "*.txt" };

            // 文件大小过滤
            yPos += rowHeight;
            lblSize = new Label { Text = "文件大小:", Location = new Point(20, yPos), Size = new Size(labelWidth, 20), TextAlign = ContentAlignment.MiddleRight };
            cmbSizeOperator = new ComboBox { Location = new Point(150, yPos), Size = new Size(80, 25), DropDownStyle = ComboBoxStyle.DropDownList };
            cmbSizeOperator.Items.AddRange(new object[] { "大于", "小于", "等于", "介于" });
            cmbSizeOperator.SelectedIndex = 0;
            txtSize1 = new TextBox { Location = new Point(240, yPos), Size = new Size(80, 25), Text = "1" };
            lblSizeUnit = new Label { Text = "MB", Location = new Point(325, yPos), Size = new Size(30, 20), TextAlign = ContentAlignment.MiddleLeft };
            lblSizeTo = new Label { Text = "到", Location = new Point(360, yPos), Size = new Size(20, 20), TextAlign = ContentAlignment.MiddleCenter, Visible = false };
            txtSize2 = new TextBox { Location = new Point(380, yPos), Size = new Size(80, 25), Visible = false };

            cmbSizeOperator.SelectedIndexChanged += (s, e) => {
                bool between = cmbSizeOperator.SelectedIndex == 3;
                lblSizeTo.Visible = between;
                txtSize2.Visible = between;
            };

            // 修改时间过滤
            yPos += rowHeight;
            lblDate = new Label { Text = "修改时间:", Location = new Point(20, yPos), Size = new Size(labelWidth, 20), TextAlign = ContentAlignment.MiddleRight };
            cmbDateOperator = new ComboBox { Location = new Point(150, yPos), Size = new Size(80, 25), DropDownStyle = ComboBoxStyle.DropDownList };
            cmbDateOperator.Items.AddRange(new object[] { "今天", "昨天", "本周", "上周", "本月", "上月", "今年", "去年", "自定义" });
            cmbDateOperator.SelectedIndex = 0;
            dtpDate1 = new DateTimePicker { Location = new Point(240, yPos), Size = new Size(150, 25), Format = DateTimePickerFormat.Short, Visible = false };
            lblDateTo = new Label { Text = "到", Location = new Point(395, yPos), Size = new Size(20, 20), TextAlign = ContentAlignment.MiddleCenter, Visible = false };
            dtpDate2 = new DateTimePicker { Location = new Point(420, yPos), Size = new Size(150, 25), Format = DateTimePickerFormat.Short, Visible = false };

            cmbDateOperator.SelectedIndexChanged += (s, e) => {
                bool custom = cmbDateOperator.SelectedIndex == 8;
                dtpDate1.Visible = custom;
                lblDateTo.Visible = custom;
                dtpDate2.Visible = custom;
            };

            // 搜索按钮
            yPos += rowHeight + 10;
            btnSearch = new Button { Text = "开始搜索", Location = new Point(150, yPos), Size = new Size(100, 35), BackColor = Color.ForestGreen, ForeColor = Color.White, FlatStyle = FlatStyle.Flat, Font = new Font("Segoe UI", 10, FontStyle.Bold) };
            btnSearch.FlatAppearance.BorderSize = 0;
            btnSearch.Click += BtnSearch_Click;

            btnStop = new Button { Text = "停止搜索", Location = new Point(260, yPos), Size = new Size(100, 35), BackColor = Color.IndianRed, ForeColor = Color.White, FlatStyle = FlatStyle.Flat, Font = new Font("Segoe UI", 10, FontStyle.Bold), Enabled = false };
            btnStop.FlatAppearance.BorderSize = 0;
            btnStop.Click += BtnStop_Click;

            // 结果列表
            yPos += rowHeight + 20;
            lstResults = new ListView { Location = new Point(20, yPos), Size = new Size(840, 300), View = View.Details, FullRowSelect = true, GridLines = true };
            lstResults.Columns.Add("文件名", 200);
            lstResults.Columns.Add("路径", 400);
            lstResults.Columns.Add("大小", 100);
            lstResults.Columns.Add("修改日期", 140);
            lstResults.SmallImageList = new ImageList();
            lstResults.SmallImageList.Images.Add(SystemIcons.File.ToBitmap());

            // 状态栏
            statusStrip = new StatusStrip();
            toolStripStatusLabel = new ToolStripStatusLabel();
            toolStripProgressBar = new ToolStripProgressBar();
            statusStrip.Items.Add(toolStripStatusLabel);
            statusStrip.Items.Add(toolStripProgressBar);
            statusStrip.Location = new Point(0, this.ClientSize.Height - 22);
            statusStrip.Size = new Size(this.ClientSize.Width, 22);
            statusStrip.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;

            // 添加控件到窗体
            this.Controls.AddRange(new Control[] {
                lblPath, txtPath, btnBrowse,
                lblPattern, txtPattern,
                lblSize, cmbSizeOperator, txtSize1, lblSizeUnit, lblSizeTo, txtSize2,
                lblDate, cmbDateOperator, dtpDate1, lblDateTo, dtpDate2,
                btnSearch, btnStop,
                lstResults, statusStrip
            });

            // 添加右键菜单
            var contextMenu = new ContextMenuStrip();
            var openFolderItem = new ToolStripMenuItem("打开所在文件夹");
            openFolderItem.Click += (s, e) => OpenContainingFolder();
            var copyPathItem = new ToolStripMenuItem("复制文件路径");
            copyPathItem.Click += (s, e) => CopyFilePath();
            contextMenu.Items.Add(openFolderItem);
            contextMenu.Items.Add(copyPathItem);
            lstResults.ContextMenuStrip = contextMenu;
        }

        #region 控件声明
        private Label lblPath, lblPattern, lblSize, lblDate;
        private TextBox txtPath, txtPattern, txtSize1, txtSize2;
        private ComboBox cmbSizeOperator, cmbDateOperator;
        private Button btnBrowse, btnSearch, btnStop;
        private Label lblSizeUnit, lblSizeTo, lblDateTo;
        private DateTimePicker dtpDate1, dtpDate2;
        private ListView lstResults;
        private StatusStrip statusStrip;
        private ToolStripStatusLabel toolStripStatusLabel;
        private ToolStripProgressBar toolStripProgressBar;
        #endregion

        #region 事件处理
        private void BtnBrowse_Click(object sender, EventArgs e)
        {
            using (FolderBrowserDialog folderDialog = new FolderBrowserDialog())
            {
                folderDialog.Description = "选择搜索目录";
                folderDialog.RootFolder = Environment.SpecialFolder.MyComputer;
                folderDialog.ShowNewFolderButton = false;

                if (folderDialog.ShowDialog() == DialogResult.OK)
                {
                    txtPath.Text = folderDialog.SelectedPath;
                }
            }
        }

        private async void BtnSearch_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(txtPath.Text) || !Directory.Exists(txtPath.Text))
            {
                MessageBox.Show("请选择有效的搜索路径", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (string.IsNullOrWhiteSpace(txtPattern.Text))
            {
                MessageBox.Show("请输入文件名模式", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // 准备UI
            btnSearch.Enabled = false;
            btnStop.Enabled = true;
            lstResults.Items.Clear();
            searchResults.Clear();
            filesScanned = 0;
            totalBytesScanned = 0;
            searchStopwatch.Restart();
            toolStripProgressBar.Value = 0;
            toolStripProgressBar.Maximum = 100;
            toolStripStatusLabel.Text = "搜索中...";

            // 创建取消令牌
            cancellationTokenSource = new CancellationTokenSource();
            CancellationToken token = cancellationTokenSource.Token;

            try
            {
                // 获取搜索参数
                string path = txtPath.Text;
                string pattern = txtPattern.Text;
                long sizeLimit = ParseSizeFilter();
                DateTime? dateFrom = ParseDateFilter(out DateTime? dateTo);

                // 执行搜索
                await Task.Run(() => SearchFiles(path, pattern, sizeLimit, dateFrom, dateTo, token), token);

                // 显示结果
                DisplayResults();
            }
            catch (OperationCanceledException)
            {
                toolStripStatusLabel.Text = "搜索已取消";
            }
            catch (Exception ex)
            {
                MessageBox.Show($"搜索过程中发生错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                toolStripStatusLabel.Text = "搜索失败";
            }
            finally
            {
                // 恢复UI
                btnSearch.Enabled = true;
                btnStop.Enabled = false;
                searchStopwatch.Stop();
                toolStripStatusLabel.Text = $"搜索完成! 共找到 {lstResults.Items.Count} 个文件, 耗时 {searchStopwatch.Elapsed.TotalSeconds:0.00} 秒";
            }
        }

        private void BtnStop_Click(object sender, EventArgs e)
        {
            cancellationTokenSource?.Cancel();
            btnStop.Enabled = false;
            toolStripStatusLabel.Text = "正在停止搜索...";
        }

        private void OpenContainingFolder()
        {
            if (lstResults.SelectedItems.Count == 0) return;

            string filePath = lstResults.SelectedItems[0].SubItems[1].Text;
            string folderPath = Path.GetDirectoryName(filePath);

            if (Directory.Exists(folderPath))
            {
                Process.Start("explorer.exe", $"/select,\"{filePath}\"");
            }
        }

        private void CopyFilePath()
        {
            if (lstResults.SelectedItems.Count == 0) return;

            string filePath = lstResults.SelectedItems[0].SubItems[1].Text;
            Clipboard.SetText(filePath);
        }
        #endregion

        #region 搜索功能实现
        private long ParseSizeFilter()
        {
            if (!long.TryParse(txtSize1.Text, out long size)) return 0;

            // 转换为字节
            switch (lblSizeUnit.Text)
            {
                case "KB": return size * 1024;
                case "MB": return size * 1024 * 1024;
                case "GB": return size * 1024 * 1024 * 1024;
                default: return size; // 默认是字节
            }
        }

        private DateTime? ParseDateFilter(out DateTime? dateTo)
        {
            dateTo = null;
            int index = cmbDateOperator.SelectedIndex;

            if (index < 8) // 非自定义
            {
                DateTime now = DateTime.Now;
                switch (index)
                {
                    case 0: // 今天
                        return now.Date;
                    case 1: // 昨天
                        return now.AddDays(-1).Date;
                    case 2: // 本周
                        return now.AddDays(-(int)now.DayOfWeek).Date;
                    case 3: // 上周
                        return now.AddDays(-(int)now.DayOfWeek - 7).Date;
                    case 4: // 本月
                        return new DateTime(now.Year, now.Month, 1);
                    case 5: // 上月
                        return new DateTime(now.Year, now.Month, 1).AddMonths(-1);
                    case 6: // 今年
                        return new DateTime(now.Year, 1, 1);
                    case 7: // 去年
                        return new DateTime(now.Year - 1, 1, 1);
                }
            }
            else // 自定义
            {
                dateTo = dtpDate2.Value;
                return dtpDate1.Value;
            }

            return null;
        }

        private void SearchFiles(string rootPath, string pattern, long sizeLimit, DateTime? dateFrom, DateTime? dateTo, CancellationToken token)
        {
            // 使用并行处理加速搜索
            var options = new ParallelOptions
            {
                CancellationToken = token,
                MaxDegreeOfParallelism = Environment.ProcessorCount
            };

            // 使用栈代替递归遍历目录
            var directories = new ConcurrentStack<string>();
            directories.Push(rootPath);

            // 使用任务并行库处理目录
            var tasks = new List<Task>();
            int taskCount = Math.Min(Environment.ProcessorCount * 2, 16); // 限制最大任务数

            for (int i = 0; i < taskCount; i++)
            {
                tasks.Add(Task.Run(() =>
                {
                    while (!token.IsCancellationRequested && directories.TryPop(out string currentDir))
                    {
                        try
                        {
                            // 处理当前目录中的文件
                            ProcessDirectory(currentDir, pattern, sizeLimit, dateFrom, dateTo, token);

                            // 获取子目录
                            var subDirs = Directory.EnumerateDirectories(currentDir);
                            foreach (var dir in subDirs)
                            {
                                if (!token.IsCancellationRequested)
                                {
                                    directories.Push(dir);
                                }
                            }
                        }
                        catch (UnauthorizedAccessException)
                        {
                            // 忽略无权限访问的目录
                        }
                        catch (PathTooLongException)
                        {
                            // 忽略路径过长的目录
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine($"处理目录时出错: {ex.Message}");
                        }
                    }
                }, token));
            }

            // 等待所有任务完成
            Task.WaitAll(tasks.ToArray(), token);
        }

        private void ProcessDirectory(string directory, string pattern, long sizeLimit, DateTime? dateFrom, DateTime? dateTo, CancellationToken token)
        {
            try
            {
                // 处理文件
                var files = Directory.EnumerateFiles(directory, pattern, SearchOption.TopDirectoryOnly);
                foreach (var file in files)
                {
                    if (token.IsCancellationRequested) return;

                    try
                    {
                        FileInfo fileInfo = new FileInfo(file);
                        bool sizeMatch = CheckSize(fileInfo.Length, sizeLimit);
                        bool dateMatch = CheckDate(fileInfo.LastWriteTime, dateFrom, dateTo);

                        if (sizeMatch && dateMatch)
                        {
                            searchResults.Add(file);
                        }

                        // 更新进度
                        Interlocked.Increment(ref filesScanned);
                        Interlocked.Add(ref totalBytesScanned, fileInfo.Length);
                        UpdateProgress();
                    }
                    catch (UnauthorizedAccessException)
                    {
                        // 忽略无权限访问的文件
                    }
                    catch (PathTooLongException)
                    {
                        // 忽略路径过长的文件
                    }
                }
            }
            catch (UnauthorizedAccessException)
            {
                // 忽略无权限访问的目录
            }
            catch (PathTooLongException)
            {
                // 忽略路径过长的目录
            }
        }

        private bool CheckSize(long fileSize, long limit)
        {
            int operatorIndex = cmbSizeOperator.SelectedIndex;
            switch (operatorIndex)
            {
                case 0: // 大于
                    return fileSize > limit;
                case 1: // 小于
                    return fileSize < limit;
                case 2: // 等于
                    return fileSize == limit;
                case 3: // 介于
                    if (long.TryParse(txtSize2.Text, out long size2))
                    {
                        long limit2 = ParseSizeFilter(txtSize2.Text, lblSizeUnit.Text);
                        return fileSize >= Math.Min(limit, limit2) && fileSize <= Math.Max(limit, limit2);
                    }
                    return fileSize >= limit;
                default:
                    return true;
            }
        }

        private long ParseSizeFilter(string sizeText, string unit)
        {
            if (!long.TryParse(sizeText, out long size)) return 0;

            switch (unit)
            {
                case "KB": return size * 1024;
                case "MB": return size * 1024 * 1024;
                case "GB": return size * 1024 * 1024 * 1024;
                default: return size;
            }
        }

        private bool CheckDate(DateTime fileDate, DateTime? dateFrom, DateTime? dateTo)
        {
            if (!dateFrom.HasValue) return true;

            if (dateTo.HasValue)
            {
                return fileDate >= dateFrom.Value && fileDate <= dateTo.Value;
            }
            else
            {
                // 单日期比较(当天)
                return fileDate.Date == dateFrom.Value.Date;
            }
        }

        private void UpdateProgress()
        {
            if (filesScanned % 100 == 0) // 每100个文件更新一次UI
            {
                int progressPercent = (int)(totalBytesScanned / (1024.0 * 1024 * 1024) * 10); // 粗略估算
                progressPercent = Math.Min(progressPercent, 100);

                this.Invoke((MethodInvoker)delegate {
                    toolStripProgressBar.Value = progressPercent;
                    toolStripStatusLabel.Text = $"搜索中... 已扫描 {filesScanned} 个文件, {totalBytesScanned / (1024 * 1024)} MB";
                });
            }
        }

        private void DisplayResults()
        {
            this.Invoke((MethodInvoker)delegate {
                foreach (var file in searchResults)
                {
                    try
                    {
                        FileInfo fileInfo = new FileInfo(file);
                        ListViewItem item = new ListViewItem(fileInfo.Name);
                        item.SubItems.Add(fileInfo.DirectoryName);
                        item.SubItems.Add(FormatFileSize(fileInfo.Length));
                        item.SubItems.Add(fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm"));
                        item.ImageIndex = 0;
                        lstResults.Items.Add(item);
                    }
                    catch
                    {
                        // 忽略无法访问的文件
                    }
                }
            });
        }

        private string FormatFileSize(long bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB", "TB" };
            int order = 0;
            double len = bytes;

            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len /= 1024;
            }

            return $"{len:0.##} {sizes[order]}";
        }
        #endregion

        #region 辅助功能
        private void LoadRecentSearches()
        {
            // 在实际应用中,这里可以从配置文件加载最近的搜索路径
        }

        private void SaveRecentSearches()
        {
            // 在实际应用中,这里可以将最近的搜索路径保存到配置文件
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            cancellationTokenSource?.Cancel();
            base.OnFormClosing(e);
        }
        #endregion
    }
}

2. 程序入口 (Program.cs)

csharp 复制代码
using System;
using System.Windows.Forms;

namespace FastFileSearch
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }
}

3. 应用程序配置文件 (App.config)

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
  </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
        <bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

功能特点

1. 高性能搜索

  • 多线程并行搜索:使用任务并行库(TPL)和多线程技术
  • 异步文件枚举:避免阻塞UI线程
  • 栈式目录遍历:避免递归导致的堆栈溢出
  • 批量UI更新:减少界面刷新次数

2. 高级过滤功能

  • 文件名模式:支持通配符(*, ?)
  • 文件大小过滤:大于、小于、等于、介于
  • 日期过滤:今天、昨天、本周、上周、本月、上月、今年、去年、自定义范围
  • 组合过滤:同时使用多种过滤条件

3. 用户友好界面

  • 直观的参数设置:分组布局,清晰的标签
  • 实时进度显示:进度条和状态信息
  • 详细结果列表:文件名、路径、大小、修改日期
  • 右键菜单:打开所在文件夹、复制文件路径
  • 响应式设计:适应不同屏幕尺寸

4. 健壮性设计

  • 异常处理:捕获并处理常见文件系统异常
  • 取消支持:随时停止长时间运行的搜索
  • 资源清理:正确释放文件句柄和系统资源
  • 权限处理:优雅地处理无权限访问的目录

技术亮点

1. 并行搜索算法

csharp 复制代码
// 使用并行处理加速搜索
var options = new ParallelOptions
{
    CancellationToken = token,
    MaxDegreeOfParallelism = Environment.ProcessorCount
};

// 使用栈代替递归遍历目录
var directories = new ConcurrentStack<string>();
directories.Push(rootPath);

// 创建多个任务处理目录
for (int i = 0; i < taskCount; i++)
{
    tasks.Add(Task.Run(() =>
    {
        while (!token.IsCancellationRequested && directories.TryPop(out string currentDir))
        {
            // 处理目录...
        }
    }, token));
}

2. 高效文件处理

csharp 复制代码
// 批量处理文件
var files = Directory.EnumerateFiles(directory, pattern, SearchOption.TopDirectoryOnly);
foreach (var file in files)
{
    if (token.IsCancellationRequested) return;
    
    FileInfo fileInfo = new FileInfo(file);
    bool sizeMatch = CheckSize(fileInfo.Length, sizeLimit);
    bool dateMatch = CheckDate(fileInfo.LastWriteTime, dateFrom, dateTo);
    
    if (sizeMatch && dateMatch)
    {
        searchResults.Add(file);
    }
    
    // 更新进度
    Interlocked.Increment(ref filesScanned);
    Interlocked.Add(ref totalBytesScanned, fileInfo.Length);
    UpdateProgress();
}

3. 智能过滤系统

csharp 复制代码
// 文件大小过滤
private bool CheckSize(long fileSize, long limit)
{
    int operatorIndex = cmbSizeOperator.SelectedIndex;
    switch (operatorIndex)
    {
        case 0: return fileSize > limit; // 大于
        case 1: return fileSize < limit; // 小于
        case 2: return fileSize == limit; // 等于
        case 3: // 介于
            if (long.TryParse(txtSize2.Text, out long size2))
            {
                long limit2 = ParseSizeFilter(txtSize2.Text, lblSizeUnit.Text);
                return fileSize >= Math.Min(limit, limit2) && 
                       fileSize <= Math.Max(limit, limit2);
            }
            return fileSize >= limit;
        default: return true;
    }
}

// 日期过滤
private bool CheckDate(DateTime fileDate, DateTime? dateFrom, DateTime? dateTo)
{
    if (!dateFrom.HasValue) return true;
    
    if (dateTo.HasValue)
    {
        return fileDate >= dateFrom.Value && fileDate <= dateTo.Value;
    }
    else
    {
        return fileDate.Date == dateFrom.Value.Date;
    }
}

4. 进度反馈机制

csharp 复制代码
// 更新进度
private void UpdateProgress()
{
    if (filesScanned % 100 == 0) // 每100个文件更新一次UI
    {
        int progressPercent = (int)(totalBytesScanned / (1024.0 * 1024 * 1024) * 10);
        progressPercent = Math.Min(progressPercent, 100);

        this.Invoke((MethodInvoker)delegate {
            toolStripProgressBar.Value = progressPercent;
            toolStripStatusLabel.Text = $"搜索中... 已扫描 {filesScanned} 个文件, {totalBytesScanned / (1024 * 1024)} MB";
        });
    }
}

使用说明

1. 基本搜索

  1. 在"搜索路径"中选择或输入要搜索的目录
  2. 在"文件名模式"中输入文件名模式(如 *.txt)
  3. 点击"开始搜索"按钮

2. 高级过滤

  • 文件大小:选择操作符并输入大小值
  • 修改时间:选择预设范围或自定义日期范围
  • 组合使用:同时使用多个过滤条件缩小搜索范围

3. 结果操作

  • 查看详情:在结果列表中查看文件详细信息
  • 打开文件夹:右键点击文件选择"打开所在文件夹"
  • 复制路径:右键点击文件选择"复制文件路径"

4. 性能优化建议

  • 避免在全盘搜索时使用过于宽泛的模式(如 .
  • 对于大型目录,使用更具体的路径
  • 合理设置文件大小过滤条件
  • 使用日期过滤减少搜索范围

参考代码 C# 快速搜索磁盘文件 www.youwenfan.com/contentcst/39200.html

扩展功能建议

1. 添加文件内容搜索

csharp 复制代码
private bool ContainsText(string filePath, string searchText)
{
    try
    {
        using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        using (var reader = new StreamReader(stream, Encoding.UTF8, true))
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                if (line.Contains(searchText))
                    return true;
            }
        }
    }
    catch
    {
        // 忽略无法读取的文件
    }
    return false;
}

2. 添加文件预览功能

csharp 复制代码
private void ShowFilePreview(string filePath)
{
    var previewForm = new Form
    {
        Text = $"预览: {Path.GetFileName(filePath)}",
        Size = new Size(600, 400)
    };
    
    var textBox = new TextBox
    {
        Multiline = true,
        ScrollBars = ScrollBars.Both,
        Dock = DockStyle.Fill,
        ReadOnly = true
    };
    
    try
    {
        textBox.Text = File.ReadAllText(filePath);
    }
    catch
    {
        textBox.Text = "无法预览此文件类型";
    }
    
    previewForm.Controls.Add(textBox);
    previewForm.ShowDialog();
}

3. 添加搜索历史记录

csharp 复制代码
private List<SearchHistoryItem> searchHistory = new List<SearchHistoryItem>();

private void SaveSearchToHistory()
{
    var historyItem = new SearchHistoryItem
    {
        Path = txtPath.Text,
        Pattern = txtPattern.Text,
        SizeOperator = cmbSizeOperator.SelectedIndex,
        SizeValue = txtSize1.Text,
        DateOperator = cmbDateOperator.SelectedIndex,
        DateValue = dtpDate1.Value
    };
    
    searchHistory.Add(historyItem);
    if (searchHistory.Count > 10) searchHistory.RemoveAt(0);
    
    // 保存到配置文件
    SaveHistoryToFile();
}

private void LoadHistoryFromFile()
{
    // 从配置文件加载历史记录
}

4. 添加文件类型图标

csharp 复制代码
// 初始化图标列表
private void InitializeIconList()
{
    lstResults.SmallImageList = new ImageList();
    lstResults.LargeImageList = new ImageList();
    
    // 添加常见文件类型图标
    AddFileIcon(".txt", SystemIcons.Document);
    AddFileIcon(".doc", OfficeIcons.Word);
    AddFileIcon(".xls", OfficeIcons.Excel);
    AddFileIcon(".pdf", SystemIcons.WinLogo);
    // 添加更多文件类型...
}

private void AddFileIcon(string extension, Icon icon)
{
    lstResults.SmallImageList.Images.Add(extension, icon);
    lstResults.LargeImageList.Images.Add(extension, icon);
}

// 在显示结果时使用图标
private void DisplayResults()
{
    foreach (var file in searchResults)
    {
        string ext = Path.GetExtension(file).ToLower();
        ListViewItem item = new ListViewItem(Path.GetFileName(file));
        item.ImageKey = lstResults.SmallImageList.Images.ContainsKey(ext) ? ext : "default";
        // 添加其他列...
        lstResults.Items.Add(item);
    }
}

性能优化技巧

  1. 目录遍历优化

    • 跳过系统目录(如 System Volume Information)
    • 忽略隐藏文件和目录
    • 使用原生API(如 P/Invoke)加速文件枚举
  2. 内存管理

    • 使用流式处理避免大文件加载到内存
    • 定期清理不再使用的对象
    • 限制结果集大小防止内存溢出
  3. 磁盘访问优化

    • 按磁盘簇大小读取文件
    • 避免频繁的磁盘寻道操作
    • 使用异步IO减少等待时间
  4. 并行处理优化

    • 根据磁盘性能调整并行度
    • 使用任务窃取(task stealing)平衡负载
    • 避免过度并行导致磁盘争用

常见问题解决

1. 搜索速度慢

  • 原因:全盘搜索或大目录搜索
  • 解决
    • 使用更具体的搜索路径
    • 添加文件大小和日期过滤
    • 避免在网络驱动器上搜索

2. 内存占用过高

  • 原因:结果集过大
  • 解决
    • 添加结果数量限制
    • 使用分页显示结果
    • 定期清理已完成任务的资源

3. 权限错误

  • 原因:访问受保护目录
  • 解决
    • 以管理员身份运行程序
    • 跳过无权限访问的目录
    • 记录无法访问的路径供用户参考

4. 文件类型识别错误

  • 原因:文件扩展名与实际类型不符
  • 解决
    • 使用文件签名(magic number)检测真实类型
    • 提供手动选择文件类型的选项
    • 允许用户添加自定义文件类型规则

项目总结

这个 C# 文件搜索工具提供了高性能的磁盘文件搜索功能,具有以下特点:

  1. 极速搜索

    • 多线程并行处理
    • 异步文件枚举
    • 智能目录遍历
  2. 强大过滤

    • 文件名模式匹配
    • 文件大小过滤
    • 修改日期过滤
    • 组合条件搜索
  3. 用户友好

    • 直观的参数设置
    • 实时进度反馈
    • 详细结果展示
    • 便捷的结果操作
  4. 健壮稳定

    • 全面的异常处理
    • 资源高效管理
    • 支持长时间运行
    • 可随时取消
相关推荐
小陈工2 小时前
2026年4月8日技术资讯洞察:边缘AI推理框架竞争白热化,Python后端开发者的机遇与挑战
开发语言·数据库·人工智能·python·微服务·回归
零二年的冬2 小时前
epoll详解
java·linux·开发语言·c++·链表
凭君语未可2 小时前
Java 中的接口是什么
java·开发语言
XiYang-DING2 小时前
【Java】二叉树
java·开发语言·数据结构
下北沢美食家2 小时前
JavaScript面试题2
开发语言·javascript·ecmascript
数据知道2 小时前
claw-code 源码分析:大型移植的测试哲学——如何用 unittest 门禁守住「诚实未完成」的口碑?
开发语言·python·ai·claude code·claw code
小堃学编程2 小时前
【项目实战】基于protobuf的发布订阅式消息队列(2)—— 线程池
java·开发语言
每日任务(希望进OD版)3 小时前
线性DP、区间DP
开发语言·数据结构·c++·算法·动态规划
怨言.3 小时前
Java内部类详解:从基础概念到实战应用(附案例)
java·开发语言