在另一文本文件中搜索一个文本文件的行,速度更快
本文关键字:文本 文件 速度 一个 搜索 | 更新日期: 2023-09-27 18:26:08
有没有比在两个文件中逐行搜索更快的方法来搜索一个文本文件的每一行,以查找另一个文件中的内容?
我有两个文本文件——一个有大约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<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文件的内容。我测试过regex,它并不比indexof快。包含将不起作用,因为行永远不会完全相同。
谢谢。
可能有一种更快的方法,但这种LINQ方法应该快于3小时,并且更便于阅读和维护:
var f1Lines = File.ReadAllLines(f1Path);
var f2LineInf1 = File.ReadLines(f2Path)
.Where( line => f1Lines.Contains(line))
.Select(line => line).ToList();
编辑:对文件2中的400000行和文件1中的17000行进行了测试,要求不到1秒。我可以对大文件使用File.ReadLines
,它不会一次将所有文件加载到内存中。对于较小的文件,我需要使用File.ReadAllLines
,因为Contains
需要文件1的完整行列表。
如果您想将结果记录在第三个文件中:
File.WriteAllLines(logPath, f2LineInf1);
EDIT:请注意,我假设将至少一个文件读入内存是合理的。你可能想交换下面的查询,以避免将"大"文件加载到内存中,但即使是每行1K的86000行,也会少于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
语句,以确保它们得到正确处理。使用上面的代码使它变得简单,甚至不需要它。。。
快速而肮脏,因为我必须去。。。如果你可以在内存中完成,请尝试使用以下片段:
//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));
}