更好用C#搜索所有文件中的字符串
在参考了很多博客和文章之后,我已经达到了以下代码,用于在文件夹内的所有文件中搜索字符串。 它在我的测试中运行良好。
质询
- 有没有更快的方法(使用C#)?
- 是否有任何方案会因此代码而失败?
注意:我测试了非常小的文件。 文件数量也很少。
码
static void Main() { string sourceFolder = @"C:\Test"; string searchWord = ".class1"; List allFiles = new List(); 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 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); } } }
参考
- 使用StreamReader检查文件是否包含字符串
- 使用两个条件拆分字符串
- C#检测路径中的文件夹连接
- 检测符号链接,连接点,挂载点和硬链接
- FolderBrowserDialog具有重新分析点的SelectedPath
- C# – 图像的高质量字节数组转换
而不是File.ReadAllText()更好地使用
File.ReadLines(@"C:\file.txt");
它返回IEnumerable
(yielding),因此如果在到达文本文件的最后一行之前找到了字符串,则不必读取整个文件
我写的东西非常相似,我建议做一些改变。
- 使用Directory.EnumerateDirectories而不是GetDirectories,它会立即返回IEnumerable,因此您无需等待它在处理之前完成所有目录的读取。
- 使用ReadLines而不是ReadAllText,这只会在内存中一次加载一行,如果你点击一个大文件,这将是一个大问题。
- 如果您使用的是足够新版本的.NET,请使用Parallel.ForEach ,这样您就可以一次搜索多个文件。
- 您可能无法打开文件,需要检查读取权限或将清单添加到您的程序需要管理权限(您仍应检查)
我正在创建一个二进制搜索工具,这里有一些我写给你的手的片段
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; }
这使用两个嵌套的并行循环。 这种设计非常低效,并且可以通过使用Booyer-Moore搜索算法大大改进,但我找不到二进制实现,而且我没有时间最初编写它来自己实现它。
这里的主要问题是您每次搜索都会实时搜索所有文件。 如果2个以上的用户同时搜索,则还存在文件访问冲突的可能性。
为了大幅度提高性能,我会提前索引文件,并在编辑/保存时进行索引。 使用类似lucene.net的东西存储索引,然后查询索引(再次使用luence.net )并将文件名返回给用户。 所以用户永远不会直接查询文件。
如果您按照此SOpost中的链接,您可能在实施索引方面有一个良好的开端。 我没有按照链接,但值得一看。
只是抬头,这将是你目前的方法的强烈转变,并将需要
- 监视/索引文件的服务
- UI项目
如果您缺少permission to open a file
我认为您的代码将失败并出现exception。
将其与此处的代码进行比较: http : //bgrep.codeplex.com/releases/view/36186
后一个代码支持
- 正则表达式搜索和
- 文件扩展名的filter
– 你应该考虑的事情。
-
而不是
Contains
更好的使用算法Boyer-Moore搜索。 -
失败场景:文件没有读取权限。
- C#/ .NET 4.5 – 为什么“等待Task.WhenAny”在WPF应用程序的UI线程中提供Task.Delay时永远不会返回?
- ‘ObjectContext’不包含’Entry’的定义,也没有扩展方法’Entry’
- silverlight mpeg-4
- 为什么Char.IsDigit对于无法解析为int的字符返回true?
- Querystring – 在c#中为querystring添加值
- .net Reflector反编译的C#代码将无法编译
- FileStream.Dispose会立即关闭文件吗?
- 如何在属性getter和带有一个参数的方法之间存在歧义?
- 您是否可以说服DataContext将列视为始终脏?