读取和处理大型文本文件〜每个100Mb

时间:2012-02-27 19:14:57

标签: c# performance backgroundworker streamreader

我有一个要处理的大文本文件列表。我想知道哪种方法最快,因为逐行阅读很慢。 我有类似的东西:

int cnt = this.listView1.Items.Count;

for (int i = 0; i < this.listView1.Items.Count; i++)
{
     FileStream fs = new FileStream(this.listView1.Items[i].Text.ToString(),             FileMode.Open, FileAccess.Read);
     using (StreamReader reader = new StreamReader(fs))
     while (reader.Peek() != -1)
          {
             //code part
          }
}

我通过具有多个线程的后台工作者阅读有关使用块(每个100k行)的信息会有所帮助,但我不知道如何实现它。或者,如果您有更好的想法来改善绩效......我们将非常感谢您的专业建议。

3 个答案:

答案 0 :(得分:4)

首先,您需要确定什么是瓶颈 - I / O(读取文件)或CPU(处理它们)。如果它是I / O,同时读取多个文件对你没什么帮助,你可以实现的最多就是有一个线程读取文件,另一个处理它们。处理线程将在下一个文件可用之前完成。

我同意@asawyer,如果它只有100MB,你应该一下子将文件完全读入内存。你不妨将其中的5个完全读入内存,这真的不是什么大问题。

编辑:确认所有文件都在一个硬盘驱动器上,并且处理所需的时间比读取文件的时间长。

你应该在线程上顺序读取文件。读取文件后,启动另一个处理处理的线程,并开始读取第一个线程中的第二个文件。读取第二个文件后,启动另一个线程,依此类推。

您应该确保不会激活比您拥有的核心数更多的处理线程,但是对于初学者来说,只需使用线程池,然后再进行优化。

您缺少一点性能,因为您花在阅读第一个文件上的时间不会用于任何处理。这应该是可以忽略不计的,将100MB的数据读取到内存中的时间不应超过几秒钟。

答案 1 :(得分:2)

我假设你是逐行处理文件。您还说加载文件比处理它们更快。您可以通过几种方式完成所需。例如:

创建一个逐行读取文件的线程。顺便说一句,因为当并行执行此操作时,您只会敲击硬盘并可能会导致更糟糕的结果。您可以使用Queue<string>。使用Queue.Enqueue()添加红色线条。

运行另一个正在处理队列的线程。使用Queue.Dequeue()从队列的开头获取(和删除)行。处理该行并将其写入输出文件。最后,您可以将处理过的行放在另一个队列或列表中,并在完成处理后立即写入。

如果输出文件中的行顺序不重要,您可以创建与CPU核心(或使用ThreadPool类)一样多的线程来进行处理(这会显着加快速度)。

[编辑] 如果输出文件中的行顺序很重要,则应将行处理限制为一个线程。或者使用单独的线程并行处理它们并实现控制输出顺序的机制。例如,您可以通过对从输入文件中读取的行(简单方法)编号,或者按照n行的块中的每个线程处理行,并按照开始处理线程的相同顺序按块写入输出块来执行此操作。

答案 2 :(得分:-1)

这是一个你可以使用的简单线程代码:(。Net 4)

//firstly get file paths from listview so you won't block the UI thread
List<string> filesPaths = new List<string>();

for (int i = 0; i < this.listView1.Items.Count; i++)
{
     filesPaths.Add(listView1.Items[i].Text.ToString());
}


//this foreach loop will fire 50 threads at same time to read 50 files
Parallel.ForEach(filesPaths, new ParallelOptions() { MaxDegreeOfParallelism = 50 }, (filepath, i, j) =>
{    
     //read file contents
     string data = File.ReadAllText(filepath);

     //do whatever you want with the contents

}); 

虽未测试......