Lor*_*ner 304 .net c# performance file-io text-files
我想逐行阅读文本文件.我想知道我是否在.NET C#范围内尽可能高效地完成它.
这是我到目前为止所尝试的:
var filestream = new System.IO.FileStream(textFilePath,
System.IO.FileMode.Open,
System.IO.FileAccess.Read,
System.IO.FileShare.ReadWrite);
var file = new System.IO.StreamReader(filestream, System.Text.Encoding.UTF8, true, 128);
while ((lineOfText = file.ReadLine()) != null)
{
//Do something with the lineOfText
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*age 296
要找到逐行读取文件的最快方法,您必须进行一些基准测试.我在计算机上做了一些小测试,但你不能指望我的结果适用于你的环境.
使用StreamReader.ReadLine
这基本上就是你的方法.由于某种原因,您将缓冲区大小设置为可能的最小值(128).增加这一点通常会提高性能.默认大小为1,024,其他好的选择是512(Windows中的扇区大小)或4,096(NTFS中的簇大小).您必须运行基准测试以确定最佳缓冲区大小.更大的缓冲区 - 如果不是更快 - 至少不比较小的缓冲区慢.
const Int32 BufferSize = 128;
using (var fileStream = File.OpenRead(fileName))
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8, true, BufferSize)) {
String line;
while ((line = streamReader.ReadLine()) != null)
// Process line
}
Run Code Online (Sandbox Code Playgroud)
该FileStream构造函数允许你指定FileOptions.例如,如果您从头到尾依次读取大文件,则可能会从中受益FileOptions.SequentialScan.再次,基准测试是您可以做的最好的事情.
使用File.ReadLines
这非常类似于您自己的解决方案,除了它是使用StreamReader固定缓冲区大小为1,024的实现.在我的计算机上,与缓冲区大小为128的代码相比,性能稍好一些.但是,通过使用更大的缓冲区大小,可以获得相同的性能提升.此方法使用迭代器块实现,不消耗所有行的内存.
var lines = File.ReadLines(fileName);
foreach (var line in lines)
// Process line
Run Code Online (Sandbox Code Playgroud)
使用File.ReadAllLines
这与前面的方法非常相似,不同之处在于此方法增加了用于创建返回的行数组的字符串列表,因此内存要求更高.但是,它返回String[]而IEnumerable<String>不允许您随机访问这些行.
var lines = File.ReadAllLines(fileName);
for (var i = 0; i < lines.Length; i += 1) {
var line = lines[i];
// Process line
}
Run Code Online (Sandbox Code Playgroud)
使用String.Split
这种方法相当慢,至少在大文件上(在511 KB文件上测试),可能是由于String.Split实现的方式.它还为所有行分配一个数组,与您的解决方案相比,增加了所需的内存.
using (var streamReader = File.OpenText(fileName)) {
var lines = streamReader.ReadToEnd().Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
// Process line
}
Run Code Online (Sandbox Code Playgroud)
我的建议是使用,File.ReadLines因为它干净,高效.如果您需要特殊的共享选项(例如您使用FileShare.ReadWrite),您可以使用自己的代码但是应该增加缓冲区大小.
Jon*_*eet 197
如果您使用的是.NET 4,只需使用File.ReadLines哪种功能即可.我怀疑这是很多和你一样,但它也可以使用FileOptions.SequentialScan和更大的缓冲区(128看起来非常小).
Fre*_* 24 33
虽然File.ReadAllLines()是读取文件的最简单方法之一,但它也是最慢的方法之一.
如果你只是想在文件中读取行而不做太多,根据这些基准测试,读取文件的最快方法是使用古老的方法:
using (StreamReader sr = File.OpenText(fileName))
{
string s = String.Empty;
while ((s = sr.ReadLine()) != null)
{
//do minimal amount of work here
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果你必须对每一行做很多事情,那么本文的结论是最好的方法如下(如果你知道要读多少行,预先分配一个字符串[]会更快):
AllLines = new string[MAX]; //only allocate memory here
using (StreamReader sr = File.OpenText(fileName))
{
int x = 0;
while (!sr.EndOfStream)
{
AllLines[x] = sr.ReadLine();
x += 1;
}
} //Finished. Close the file
//Now parallel process each line in the file
Parallel.For(0, AllLines.Length, x =>
{
DoYourStuff(AllLines[x]); //do your work here
});
Run Code Online (Sandbox Code Playgroud)
小智 11
使用以下代码:
foreach (string line in File.ReadAllLines(fileName))
Run Code Online (Sandbox Code Playgroud)
这是阅读表现的巨大差异.
它以内存消耗为代价,但完全值得!
在 Stack Overflow 问题“收益回报”比“老派”回报慢吗?.
它说:
ReadAllLines 将所有行加载到内存中并返回一个 string[]。如果文件很小,一切都很好。如果文件大于内存容量,则会耗尽内存。
另一方面,ReadLines 使用 yield return 一次返回一行。有了它,您可以读取任何大小的文件。它不会将整个文件加载到内存中。
假设您要查找包含单词“foo”的第一行,然后退出。使用 ReadAllLines,您必须将整个文件读入内存,即使“foo”出现在第一行。使用 ReadLines,您只能阅读一行。哪个会更快?
如果文件不大,那么读取整个文件然后再分割它会更快
var filestreams = sr.ReadToEnd().Split(Environment.NewLine,
StringSplitOptions.RemoveEmptyEntries);
Run Code Online (Sandbox Code Playgroud)