要找到逐行读取文件的最快方法,您必须进行一些基准测试。我在我的计算机上做了一些小测试,但您不能指望我的结果适用于您的环境。
使用 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
}
}
The FileStream
构造函数允许您指定文件选项。例如,如果您从头到尾顺序读取一个大文件,您可能会受益于FileOptions.SequentialScan
。再次强调,基准测试是你能做的最好的事情。
使用 File.ReadLines
这与您自己的解决方案非常相似,只是它是使用StreamReader
固定缓冲区大小为 1,024。在我的计算机上,与缓冲区大小为 128 的代码相比,这会带来稍好的性能。但是,通过使用更大的缓冲区大小,您可以获得相同的性能提升。此方法使用迭代器块实现,并且不会消耗所有行的内存。
var lines = File.ReadLines(fileName);
foreach (var line in lines)
// Process line
使用 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
}
使用 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
}
我的建议是使用File.ReadLines因为它干净、高效。如果您需要特殊的共享选项(例如您使用FileShare.ReadWrite
),您可以使用自己的代码,但应该增加缓冲区大小。