并行读取一个非常大的文件 C#

Read a very large files in parallel C#

我有 20 多个文件,每个文件包含近 100 万行(5 GB),我需要加快读取过程,所以我尝试并行读取这些文件,但需要更长的时间时间比顺序阅读它们。有没有办法并行读取非常大的文件?

 Parallel.ForEach(sourceFilesList, filePath =>
 {
     if (!string.IsNullOrEmpty(filePath) && File.Exists(filePath))
     {
          StreamReader str = new StreamReader(filePath);
          while (!str.EndOfStream)
          {
              var temporaryObj = new object();
              string line = str.ReadLine();
              // process line here 
          }
     }
});

它的IO操作,建议像下面这样使用Async/Await(主要使用ReadAsync函数,有助于异步读取),Async/Await使用你们 Machine Physical Core 的效率很高。

public void ReadFiles()
{
  List<string> paths = new List<string>(){"path1", "path2", "path3"};
  foreach(string path in Paths)
  {
      await ProcessRead(path);
  }
}

public async void ProcessRead(filePath)
{
    if (File.Exists(filePath) == false)
    {
        Debug.WriteLine("file not found: " + filePath);
    }
    else
    {
        try
        {
            string text = await ReadTextAsync(filePath);
            Debug.WriteLine(text);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }
}

private async Task<string> ReadTextAsync(string filePath)
{
    using (FileStream sourceStream = new FileStream(filePath,
        FileMode.Open, FileAccess.Read, FileShare.Read,
        bufferSize: 4096, useAsync: true))
    {
        StringBuilder sb = new StringBuilder();

        byte[] buffer = new byte[0x1000];
        int numRead;
        while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
        {
            string text = Encoding.Unicode.GetString(buffer, 0, numRead);
            sb.Append(text);
        }

        return sb.ToString();
    }
}

代码取自MSDN:Using Async for File Access (C# and Visual Basic)

最好对大文件使用缓冲 reader。这样的事情会有所帮助。

using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read, 
FileShare.ReadWrite))
using (BufferedStream bs = new BufferedStream(fs))
using (StreamReader sr = new StreamReader(bs))
{
    string line;
    while ((line = sr.ReadLine()) != null)
    {

    }
}

为什么 BufferedStream 更快

缓冲区是内存中的一个字节块,用于缓存数据,从而减少对操作系统的调用次数。缓冲区提高读写性能。缓冲区可用于读取或写入,但不能同时用于两者。 BufferedStream 的 Read 和 Write 方法自动维护缓冲区。