快速比较两个巨大文本文件的内容

我基本上要做的是比较两个巨大的文本文件,如果匹配写出一个字符串,我写了这个,但它非常慢。 我希望你们有更好的主意。 在下面的例子中,我正在比较collect [3] splitfound [0]

string[] collectionlist = File.ReadAllLines(@"C:\found.txt"); string[] foundlist = File.ReadAllLines(@"C:\collection_export.txt"); foreach (string found in foundlist) { string[] spltifound = found.Split('|'); string matchfound = spltifound[0].Replace(".txt", ""); ; foreach (string collect in collectionlist) { string[] splitcollect = collect.Split('\\'); string matchcollect = splitcollect[3].Replace(".txt", ""); if (matchcollect == matchfound) { end++; long finaldest = (start - end); Console.WriteLine(finaldest); File.AppendAllText(@"C:\copy.txt", "copy \"" + collect + "\" \"C:\\OUT\\" + spltifound[1] + "\\" + spltifound[0] + ".txt\"\n"); break; } } } 

对不起,模糊的人,

我想要做的就是简单地说,如果一个文件中的内容存在于另一个文件中,则写出一个字符串(字符串不重要,只是找到两个比较的时间)。 collectionlist是这样的:
苹果|农场

foundlist就是这样的
C:\牛\马\ turtle.txt
C:\牛\猪\ apple.txt

我正在做的是从收集列表中取苹果,并在foundlist中找到包含apple的行。 然后写出一个基本的Windows副本批处理文件。 对困惑感到抱歉。

回答(所有信贷给Slaks)

  string[] foundlist = File.ReadAllLines(@"C:\found.txt"); var collection = File.ReadLines(@"C:\collection_export.txt") .ToDictionary(s => s.Split('|')[0].Replace(".txt","")); using (var writer = new StreamWriter(@"C:\Copy.txt")) { foreach (string found in foundlist) { string[] splitFound = found.Split('\\'); string matchFound = Path.GetFileNameWithoutExtension(found); string collectedLine; if (collection.TryGetValue(matchFound,out collectedLine)) { string[] collectlinesplit = collectedLine.Split('|'); end++; long finaldest = (start - end); Console.WriteLine(finaldest); writer.WriteLine("copy \"" + found + "\" \"C:\\O\\" + collectlinesplit[1] + "\\" + collectlinesplit[0] + ".txt\""); } } } 

  • 调用File.ReadLines() (.NET 4)而不是ReadAllLines() (.NET 2.0)。
    ReadAllLines需要构建一个数组来保存返回值,这对于大文件来说可能非常慢。
    如果您不使用.Net 4.0,请将其替换为StreamReader。

  • 使用matchCollect s(一次)构建Dictionary ,然后遍历foundList并检查HashSet是否包含matchFound
    这允许您使用O(1)散列检查替换O(n)内循环

  • 使用StreamWriter而不是调用AppendText

  • 编辑 :调用Path.GetFileNameWithoutExtension和其他Path方法而不是手动操作字符串。

例如:

 var collection = File.ReadLines(@"C:\found.txt") .ToDictionary(s => s.Split('\\')[3].Replace(".txt", "")); using (var writer = new StreamWriter(@"C:\Copy.txt")) { foreach (string found in foundlist) { string splitFound = found.Split('|'); string matchFound = Path.GetFileNameWithoutExtension(found) string collectedLine; if (collection.TryGetValue(matchFound, collectedLine)) { end++; long finaldest = (start - end); Console.WriteLine(finaldest); writer.WriteLine("copy \"" + collectedLine + "\" \"C:\\OUT\\" + splitFound[1] + "\\" + spltifound[0] + ".txt\""); } } } 

首先,我建议对这两个文件进行规范化,然后将其中一个放入一个集合中。 这使您可以快速测试是否存在特定行,并将复杂度从O(n * n)降低到O(n)。

此外,每次写一行时都不应该打开和关闭文件:

 File.AppendAllText(...); // This causes the file to be opened and closed. 

在操作开始时打开输出文件一次,向其写入行,然后在写入所有行时关闭它。

你有一个笛卡尔积,因此有必要对一边进行索引而不是进行一次冗长的线性搜索。

从一个文件中提取密钥,并使用Set或SortedList数据结构来保存它们。 这将使查找速度更快。 (你的整体算法将是O(N lg N)而不是O(N ** 2))