我有100000行的大型txt文件。 我需要启动n-count个线程并从该文件中为每个线程提供uniq行。 做这个的最好方式是什么?我想我需要逐行读取文件,迭代器必须是全局的才能锁定它。将txt文件加载到列表将非常耗时,我可以收到OutofMemory异常。有任何想法吗?用一些代码帮助plz。
答案 0 :(得分:37)
您可以使用File.ReadLines Method逐行读取文件,而无需一次将整个文件加载到内存中,Parallel.ForEach Method可以并行处理多个线程中的行:
Parallel.ForEach(File.ReadLines("file.txt"), (line, _, lineNumber) =>
{
// your code here
});
答案 1 :(得分:15)
执行我自己的基准测试,将61,277,203行加载到内存中并将值推送到Dictionary / ConcurrentDictionary()后,结果似乎支持@dtb上面的答案,使用以下方法是最快的:
Parallel.ForEach(File.ReadLines(catalogPath), line =>
{
});
我的测试还显示以下内容:
我已提供此模式的示例以供参考,因为它未包含在此页面中:
var inputLines = new BlockingCollection<string>();
ConcurrentDictionary<int, int> catalog = new ConcurrentDictionary<int, int>();
var readLines = Task.Factory.StartNew(() =>
{
foreach (var line in File.ReadLines(catalogPath))
inputLines.Add(line);
inputLines.CompleteAdding();
});
var processLines = Task.Factory.StartNew(() =>
{
Parallel.ForEach(inputLines.GetConsumingEnumerable(), line =>
{
string[] lineFields = line.Split('\t');
int genomicId = int.Parse(lineFields[3]);
int taxId = int.Parse(lineFields[0]);
catalog.TryAdd(genomicId, taxId);
});
});
Task.WaitAll(readLines, processLines);
以下是我的基准测试:
我怀疑在某些处理条件下,生产者/消费者模式可能胜过简单的Parallel.ForEach(File.ReadLines())模式。但是,在这种情况下并没有。
答案 2 :(得分:7)
在一个线程上读取文件,将其行添加到blocking queue。启动从该队列中读取的N
个任务。设置队列的max size以防止内存不足错误。
答案 3 :(得分:4)
类似的东西:
public class ParallelReadExample
{
public static IEnumerable LineGenerator(StreamReader sr)
{
while ((line = sr.ReadLine()) != null)
{
yield return line;
}
}
static void Main()
{
// Display powers of 2 up to the exponent 8:
StreamReader sr = new StreamReader("yourfile.txt")
Parallel.ForEach(LineGenerator(sr), currentLine =>
{
// Do your thing with currentLine here...
} //close lambda expression
);
sr.Close();
}
}
认为它会起作用。 (这里没有C#编译器/ IDE)
答案 4 :(得分:2)
如果要将线程数限制为n
,最简单的方法是使用AsParallel()
和WithDegreeOfParallelism(n)
来限制线程数:
string filename = "C:\\TEST\\TEST.DATA";
int n = 5;
foreach (var line in File.ReadLines(filename).AsParallel().WithDegreeOfParallelism(n))
{
// Process line.
}
答案 5 :(得分:2)
正如上面提到的@dtb,读取文件然后处理文件中各行的最快方法是: 1)将File.ReadAllLines()放入数组中 2)使用Parallel.For循环迭代数组。
You can read more performance benchmarks here.
您必须编写的代码的基本要点是:
string[] AllLines = File.ReadAllLines(fileName);
Parallel.For(0, AllLines.Length, x =>
{
DoStuff(AllLines[x]);
//whatever you need to do
});
随着.Net4中更大的阵列大小的引入,只要你有足够的内存,这应该不是问题。