使用C#更好地搜索所有文件中的字符串

LCJ*_*LCJ 28 .net c# file-io

在参考了很多博客和文章之后,我已经达到了以下代码,用于在文件夹内的所有文件中搜索字符串.它在我的测试中运行良好.

质询

  1. 有没有更快的方法(使用C#)?
  2. 是否有任何方案会因此代码而失败?

注意:我测试了非常小的文件.文件数量也很少.

static void Main()
    {
        string sourceFolder = @"C:\Test";
        string searchWord = ".class1";

        List<string> allFiles = new List<string>();
        AddFileNamesToList(sourceFolder, allFiles);
        foreach (string fileName in allFiles)
        {
            string contents = File.ReadAllText(fileName);
            if (contents.Contains(searchWord))
            {
                Console.WriteLine(fileName);
            }
        }

        Console.WriteLine(" ");
        System.Console.ReadKey();
    }

    public static void AddFileNamesToList(string sourceDir, List<string> allFiles)
    {

            string[] fileEntries = Directory.GetFiles(sourceDir);
            foreach (string fileName in fileEntries)
            {
                allFiles.Add(fileName);
            }

            //Recursion    
            string[] subdirectoryEntries = Directory.GetDirectories(sourceDir);
            foreach (string item in subdirectoryEntries)
            {
                // Avoid "reparse points"
                if ((File.GetAttributes(item) & FileAttributes.ReparsePoint) != FileAttributes.ReparsePoint)
                {
                    AddFileNamesToList(item, allFiles);
                }
            }

    }
Run Code Online (Sandbox Code Playgroud)

参考

  1. 使用StreamReader检查文件是否包含字符串
  2. 使用两个条件拆分字符串
  3. C#检测路径中的文件夹连接
  4. 检测符号链接,连接点,挂载点和硬链接
  5. FolderBrowserDialog具有重新分析点的SelectedPath
  6. C# - 图像的高质量字节数组转换

Vla*_*adL 26

而不是File.ReadAllText()更好地使用

File.ReadLines(@"C:\file.txt");
Run Code Online (Sandbox Code Playgroud)

返回IEnumerable(已产生),因此如果在到达文本文件的最后一行之前找到了字符串,则不必读取整个文件


Sco*_*ain 10

我写的东西非常相似,我建议做一些改变.

  1. 使用Directory.EnumerateDirectories而不是GetDirectories,它会立即返回IEnumerable,因此您无需等待它在处理之前完成所有目录的读取.
  2. 使用ReadLines而不是ReadAllText,这只会在内存中一次加载一行,如果你点击一个大文件,这将是一个大问题.
  3. 如果您使用的是足够新版本的.NET,请使用Parallel.ForEach,这样您就可以一次搜索多个文件.
  4. 您可能无法打开该文件,您需要检查读取权限或将清单添加到您的程序需要管理权限(您仍应检查)

我正在创建一个二进制搜索工具,这里有一些我写给你的手的片段

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    Parallel.ForEach(Directory.EnumerateFiles(_folder, _filter, SearchOption.AllDirectories), Search);
}

//_array contains the binary pattern I am searching for.
private void Search(string filePath)
{
    if (Contains(filePath, _array))
    {
        //filePath points at a match.
    }
}

private static bool Contains(string path, byte[] search)
{
    //I am doing ReadAllBytes due to the fact that I am doing a binary search not a text search
    //  There are no "Lines" to seperate out on.
    var file = File.ReadAllBytes(path);
    var result = Parallel.For(0, file.Length - search.Length, (i, loopState) =>
        {
            if (file[i] == search[0])
            {
                byte[] localCache = new byte[search.Length];
                Array.Copy(file, i, localCache, 0, search.Length);
                if (Enumerable.SequenceEqual(localCache, search))
                    loopState.Stop();
            }
        });
    return result.IsCompleted == false;
}
Run Code Online (Sandbox Code Playgroud)

这使用两个嵌套的并行循环.这种设计非常低效,并且可以通过使用Booyer-Moore搜索算法大大改进,但是我找不到二进制实现,并且我没有时间我最初编写它来自己实现它.


归档时间:

查看次数:

38576 次

最近记录:

9 年,11 月 前