有没有一种更快的方法来搜索一个文本文件的每一行在另一个文本文件中出现,而不是在两个文件中逐行搜索?
我有两个文本文件--一个有大约2500行(让我们称之为TxtA),另一个有大约86000行(TxtB)。我想在TxtB中搜索TxtA中的每一行,并在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<string> dblines = new List<string>();
String newDataPath = @"C:\WindowsApps\CRM\crm_interface\data\";
StreamReader nsr = new StreamReader(newDataPath + "HolidayList1.txt");
List<string> new1 = new List<string>();
string dbline;
string newline;
List<string> results = new List<string>();
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快。Contains将不起作用,因为这些行永远不会完全相同。
谢谢。
发布于 2012-02-29 07:09:29
编辑:请注意,我假设将至少一个文件读入内存是合理的。您可能希望交换下面的查询,以避免将“大”文件加载到内存中,但即使是每行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语句,以确保它们得到正确的处理。使用上面的代码,即使不需要它也很简单…
发布于 2012-02-29 07:08:38
可能有一个更快的方法,但是这个LINQ apporoach应该比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);发布于 2012-02-29 08:23:03
又快又脏因为我得走了..。如果可以在内存中执行此操作,请尝试使用以下代码片段:
//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));
}https://stackoverflow.com/questions/9491181
复制相似问题