Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 什么';逐行读取文本文件的最快方法是什么?_C#_.net_Performance_File Io_Text Files - Fatal编程技术网

C# 什么';逐行读取文本文件的最快方法是什么?

C# 什么';逐行读取文本文件的最快方法是什么?,c#,.net,performance,file-io,text-files,C#,.net,Performance,File Io,Text Files,我想逐行读一个文本文件。我想知道我是否在.NETC#范围内尽可能高效地完成了这项工作 这就是我目前正在尝试的: var filestream = new System.IO.FileStream(textFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read,

我想逐行读一个文本文件。我想知道我是否在.NETC#范围内尽可能高效地完成了这项工作

这就是我目前正在尝试的:

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
}

如果您使用的是.NET4,只需使用它即可。我怀疑它与您的大致相同,只是它可能也会使用一个更大的缓冲区(128似乎很小)。

如果您有足够的内存,我发现通过将整个文件读入,然后打开该文件上的流读取器来读取行,可以提高性能。只要您确实计划读取整个文件,这可以带来一些改进。

如果文件大小不大,那么读取整个文件并在以后拆分它会更快

var filestreams = sr.ReadToEnd().Split(Environment.NewLine, 
                              StringSplitOptions.RemoveEmptyEntries);

如果您想使用现有的API来读取这些行,那么就无法加快速度。但是读取较大的块并手动查找读取缓冲区中的每一行可能会更快。

要找到逐行读取文件的最快方法,您必须进行一些基准测试。我在我的计算机上做了一些小测试,但你不能期望我的结果适用于你的环境

使用StreamReader.ReadLine

这基本上就是你的方法。出于某种原因,您将缓冲区大小设置为可能的最小值(128)。增加这一点通常会提高性能。默认大小是1024,其他好的选择是512(Windows中的扇区大小)或4096(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
  }
FileStream
构造函数允许您指定。例如,如果您正在从头到尾顺序读取一个大文件,您可能会受益于
FileOptions.SequentialScan
。同样,基准测试是你能做的最好的事情

使用File.ReadLines

这与您自己的解决方案非常相似,只是它是使用固定缓冲区大小为1024的
StreamReader
实现的。在我的计算机上,与缓冲区大小为128的代码相比,这会产生稍好的性能。但是,通过使用更大的缓冲区大小,可以获得相同的性能提高。此方法使用迭代器块实现,不会为所有行消耗内存

var lines = File.ReadLines(fileName);
foreach (var line in lines)
  // Process line
使用File.ReadAllLines

这与前面的方法非常相似,只是此方法增加了用于创建返回行数组的字符串列表,因此内存要求更高。但是,它返回
String[]
,而不是
IEnumerable
,允许您随机访问这些行

var lines = File.ReadAllLines(fileName);
for (var i = 0; i < lines.Length; i += 1) {
  var line = lines[i];
  // Process line
}

我的建议是使用,因为它是干净和有效的。如果您需要特殊的共享选项(例如使用
FileShare.ReadWrite
),您可以使用自己的代码,但应增加缓冲区大小。

使用以下代码:

foreach (string line in File.ReadAllLines(fileName))
这是阅读表现上的巨大差异


它是以内存消耗为代价的,但完全值得

在堆栈溢出问题中有一个很好的主题

它说:

ReadAllLines将所有行加载到内存中并返回 字符串[]。如果文件很小,一切都很好。如果文件是 大于内存中所能容纳的大小,您将耗尽内存

另一方面,ReadLines使用yield return返回一行 一段时间。使用它,您可以读取任何大小的文件。它不会加载整个系统 将文件保存到内存中

假设您想找到包含单词“foo”的第一行, 然后退出。使用ReadAllLines,您必须读取整个文件 进入内存,即使“foo”出现在第一行。使用ReadLines, 你只读了一行。哪一个更快


虽然
File.ReadAllLines()
是读取文件的最简单方法之一,但它也是最慢的方法之一

如果您只是想在不做太多工作的情况下读取文件中的行,那么读取文件的最快方法是古老的方法:

using (StreamReader sr = File.OpenText(fileName))
{
        string s = String.Empty;
        while ((s = sr.ReadLine()) != null)
        {
               //do minimal amount of work here
        }
}
但是,如果您必须对每一行进行大量处理,则得出以下结论:最好的方法是(如果您知道要读取多少行,则预分配字符串[]会更快):


通过
faster
您的意思是从性能或开发角度来看?这将在方法期间锁定文件。您可以在数组中使用File.ReadAllLines,然后处理array.BTW,将
filestream=new filestream
括在
using()
语句中,以避免锁定文件句柄可能出现的恼人问题。关于封闭filestream is using()语句,请参阅StackOverflow,了解推荐的方法:I think ReadToEnd()更快。
File.ReadAllLines
似乎是一个更好的选择。@jgauffin我不知道File.ReadAllLines()的实现背后是什么,但我认为它有一个有限的缓冲区,并且fileReadtoEnd缓冲区应该更大,所以这样可以减少对文件的访问次数,在文件大小不大的情况下执行string.Split比多次访问文件快。我怀疑
file.ReadAllLines
是否有固定的缓冲区大小,因为文件大小是已知的。@jgauffin:in.NET 4.0
file.ReadAllLines
创建一个列表,并使用
StreamReader.ReadLine
(可能会重新分配基础数组)。此方法使用默认缓冲区大小1024。
StreamReader.ReadToEnd
避免了行解析部分,如果需要,可以在构造函数中设置缓冲区大小。定义“大”会很有帮助关于文件大小。谢谢-你在StreamReader的构造函数中包含了buffer size参数真的很有帮助。我是从Amazon的S3 API流式传输的,使用匹配的缓冲区大小与ReadLine()结合使用会大大加快速度。我不明白。在
using (StreamReader sr = File.OpenText(fileName))
{
        string s = String.Empty;
        while ((s = sr.ReadLine()) != null)
        {
               //do minimal amount of work here
        }
}
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
});