C# 如何使用缓冲区和多线程在大型文本文件中搜索字符串
我想在一个非常大的文本文件(包含数十GB的文本)中找到一个字符串。我需要使用缓冲区和多线程,这就是我想做的:C# 如何使用缓冲区和多线程在大型文本文件中搜索字符串,c#,multithreading,search,C#,Multithreading,Search,我想在一个非常大的文本文件(包含数十GB的文本)中找到一个字符串。我需要使用缓冲区和多线程,这就是我想做的: 在每次迭代中使用缓冲区创建一个循环读取文本块 将区块分割为给定数量的线程 每个线程将在收到的文本部分搜索字符串 如果找到字符串,请打印其位置,否则请读取文本文件的另一块 这就是我试图做的: string[] lines = System.IO.File.ReadAllLines(@textfile); int counter = lines.Length / nT
string[] lines = System.IO.File.ReadAllLines(@textfile);
int counter = lines.Length / nThreads;
int start = 0;
int end = counter;
(int,int)[] results = new (int, int)[nThreads];
results.ToList().ForEach(i => Console.WriteLine(i.ToString()));
for (int i = 0; i < nThreads; i++)
{
Thread thread1 = new Thread(() => { results[i] = ThreadSearch.SubarraySearch(StringToSearch, Delta, lines, start, end); });
// ThreadSearch - function that search the string in the array
thread1.Start();
thread1.Join();
}
// at the end i will go through the results array see if any of the threads found something
}
string[]lines=System.IO.File.ReadAllLines(@textfile);
int计数器=行数。长度/n读取数;
int start=0;
int end=计数器;
(int,int)[]结果=新的(int,int)[n读取];
results.ToList().ForEach(i=>Console.WriteLine(i.ToString());
对于(int i=0;i{results[i]=ThreadSearch.subraysearch(StringToSearch,Delta,lines,start,end);});
//ThreadSearch—在数组中搜索字符串的函数
thread1.Start();
thread1.Join();
}
//最后,我将遍历results数组,看看是否有线程发现了什么
}
现在我在实现该算法时遇到两个问题:
private object _mtx = new();
private List<long> _foundPositions = new();
public void StartMultireader()
{
int ncores = 16; // add manually/from config file/from CPU detection
for (int i = 0; i < ncores; i++)
Task.Run(() => FindKeyword(i));
}
private void FindKeyword(int fileChunk)
{
OpenFileStream(fileChunk);
SearchAndUpdateResult();
}
private void SearchAndUpdateResult()
{
long position = 0;
//search;
{
//if found
{
lock (_mtx)
{
_foundPositions.Add(position);
}
}
}
}
private void OpenFileStream(int fileChunk)
{
}
私有对象_mtx=new();
私有列表_foundPositions=new();
public void StartMultireader()
{
int ncores=16;//手动添加/来自配置文件/来自CPU检测
for(int i=0;iFindKeyword(i));
}
私有void FindKeyword(int fileChunk)
{
OpenFileStream(fileChunk);
SearchAndUpdateResult();
}
私有void SearchAndUpdateResult()
{
长位置=0;
//搜索;
{
//如果找到
{
锁(mtx)
{
_创建位置。添加(位置);
}
}
}
}
私有void OpenFileStream(int fileChunk)
{
}
string filePath = @"C:\YourFile.txt";
string searchedText = "TheTextToFind";
bool fileContainsText = File
.ReadLines(filePath)
.AsParallel()
.WithDegreeOfParallelism(Environment.ProcessorCount)
.Any(line => line.Contains(searchedText, StringComparison.Ordinal));
此解决方案使用该方法,因此它在假定searchedText
不包含CR或LF字符的情况下工作。否则将不会检测到该字符串
上述解决方案不太可能比普通LINQ查询更快,因为将每一行传递给不同线程会带来同步开销。一种更复杂的方法是分批处理生产线,比如说,每批处理1000条生产线。目前没有用于批处理可枚举项的内置运算符,但您可以使用包中的Buffer
运算符:
您还可以使用软件包中的批处理运算符
EnumerablePartitionOptions.NoBuffering
配置通过指示PLINQ避免缓冲输入可枚举元素,而是立即处理每个新接收的元素,从而优化内存使用。这在处理批处理时很重要,因为每个批处理的内存都非常大,尽快回收内存比最小化同步开销更重要(这是缓冲查询输入的目的,默认行为).如果搜索的文本恰好在两个连续缓冲区之间的边界处被一分为二,该怎么办?指令是使用缓冲区读取文件(因为文件太大,无法一次读取),并在perellal中使用多个线程来查找“非常大”的字符串-为可能的大小编写一个示例。线程的最大缓冲区大小is10k@Dana如果你想在文章中添加新的细节,而不是在评论中,新读者不一定会在评论中搜索。
bool fileContainsText = Partitioner
.Create(File.ReadLines(filePath).Buffer(1000),
EnumerablePartitionerOptions.NoBuffering)
.AsParallel()
.WithDegreeOfParallelism(Environment.ProcessorCount)
.Any(array => array.Any(line =>
line.Contains(searchedText, StringComparison.Ordinal)));