在另一个文本文件中搜索一个文本文件的行,速度更快

是否有更快的方法来搜索一个文本文件的每一行以便在另一个文本文件中出现,而不是在两个文件中逐行进行?

我有两个文本文件 – 一个有~2500行(我们称之为TxtA),另一个有~86000行(TxtB)。 我想在TxtA中为每一行搜索TxtB,并在找到的每个匹配项中返回TxtB中的行。

我目前将此设置为:对于TxtA中的每一行,逐行搜索TxtB以进行匹配。 然而,这需要很长时间才能完成。 似乎需要1-3个小时才能找到所有的比赛。

这是我的代码……

private static void getGUIDAndType() { try { Console.WriteLine("Begin."); System.Threading.Thread.Sleep(4000); String dbFilePath = @"C:\WindowsApps\CRM\crm_interface\data\"; StreamReader dbsr = new StreamReader(dbFilePath + "newdbcontents.txt"); List dblines = new List(); String newDataPath = @"C:\WindowsApps\CRM\crm_interface\data\"; StreamReader nsr = new StreamReader(newDataPath + "HolidayList1.txt"); List new1 = new List(); string dbline; string newline; List results = new List(); while ((newline = nsr.ReadLine()) != null) { //Reset dbsr.BaseStream.Position = 0; dbsr.DiscardBufferedData(); while ((dbline = dbsr.ReadLine()) != null) { newline = newline.Trim(); if (dbline.IndexOf(newline) != -1) {//if found... get all info for now Console.WriteLine("FOUND: " + newline); System.Threading.Thread.Sleep(1000); new1.Add(newline); break; } else {//the first line of db does not contain this line... //go to next dbline. Console.WriteLine("Lines do not match - continuing"); continue; } } Console.WriteLine("Going to next new Line"); System.Threading.Thread.Sleep(1000); //continue; } nsr.Close(); Console.WriteLine("Writing to dbc3.txt"); System.IO.File.WriteAllLines(@"C:\WindowsApps\CRM\crm_interface\data\dbc3.txt", results.ToArray()); Console.WriteLine("Finished. Press ENTER to continue."); Console.WriteLine("End."); Console.ReadLine(); } catch (Exception ex) { Console.WriteLine("Error: " + ex); Console.ReadLine(); } } 

如果有更快的方法,请告诉我。 最好是需要5-10分钟的东西…我听说过索引,但对txt文件没有太多了解。 我已经测试了正则表达式,它并不比indexof快。 包含将无法工作,因为这些行永远不会完全相同。

谢谢。

编辑:请注意,我认为将至少一个文件读入内存是合理的。 您可能希望交换下面的查询以避免将“大”文件加载到内存中,但即使是每行1K(例如)1K的86,000行也将小于2G的内存 – 这对于执行重要操作相对较少。

你每次都在阅读“内部”文件。 没有必要这样做。 将两个文件加载到内存中并从那里开始。 哎呀,对于完全匹配,你可以轻松地完成LINQ中的所有事情:

 var query = from line1 in File.ReadLines("newDataPath + "HolidayList1.txt") join line2 in File.ReadLines(dbFilePath + "newdbcontents.txt") on line1 equals line2 select line1; var commonLines = query.ToList(); 

但对于非连接,它仍然很简单; 首先完全读取一个文件(显式),然后流式传输另一个文件:

 // Eagerly read the "inner" file var lines2 = File.ReadAllLines(dbFilePath + "newdbcontents.txt"); var query = from line1 in File.ReadLines("newDataPath + "HolidayList1.txt") from line2 in lines2 where line2.Contains(line1) select line1; var commonLines = query.ToList(); 

这里没有什么聪明 – 它只是一种编写代码来读取一个文件中所有行的简单方法,然后迭代另一个文件中的行,并针对第一个文件中的所有行进行每行检查。 但即使没有任何聪明的东西,我强烈怀疑它对你来说表现还算不错。 专注于简单,消除不必要的IO,并在尝试做任何更好的事情之前看看它是否足够好。

请注意,在原始代码中,您应该使用StreamReader变量的using语句,以确保它们得到正确处理。 使用上面的代码很简单,甚至不需要它…

可能有更快的方法,但这个LINQ应用程序应该超过3个小时,并且是一个更好的阅读和维护:

 var f1Lines = File.ReadAllLines(f1Path); var f2LineInf1 = File.ReadLines(f2Path) .Where( line => f1Lines.Contains(line)) .Select(line => line).ToList(); 

编辑 :对于file2中的400000行和file1中的17000行,测试并且需要不到1秒。 我可以将File.ReadLines用于大文件,它不会立即将所有内容加载到内存中。 对于较小的文件,我需要使用File.ReadAllLines因为Contains需要文件1的完整行列表。

如果要将结果记录在第三个文件中:

 File.WriteAllLines(logPath, f2LineInf1); 

快速而肮脏,因为我必须去…如果你可以在内存中做,请尝试使用此代码段:

  //string[] searchIn = File.ReadAllLines("File1.txt"); //string[] searchFor = File.ReadAllLines("File2.txt"); string[] searchIn = new string[] {"A","AB","ABC","ABCD", null, "", " "}; string[] searchFor = new string[] {"A","BC","BCD", null, "", " "}; matchDictionary; foreach(string item in file2Content) { string[] matchingItems = Array.FindAll(searchIn, x => (x == item) || (!string.IsNullOrEmpty(x) && !string.IsNullOrEmpty(item) ? (x.Contains(item) || item.Contains(x)) : false)); }