【问题标题】:Read a very large files in parallel C#并行读取非常大的文件 C#
【发布时间】:2018-03-28 14:25:04
【问题描述】:

我有 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 
          }
     }
});

【问题讨论】:

  • 什么样的文件?
  • 您如何确定问题不是您在处理过程中所做的?
  • 是文本文件,
  • 我看到你是这个网站的新手......所以,欢迎来到 StackOverflow......如果你先做一些研究,你会很容易更快地解决你的问题..@ 987654321@
  • 这很可能是 IO 瓶颈……您可以做的是对代码进行基准测试并查明瓶颈所在。读完每一行后你会做什么?如果你没有足够快地处理它们,内存也可能是一个问题。

标签: c# multithreading streamreader


【解决方案1】:

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

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 方法自动维护缓冲区。

【讨论】:

  • FileStream 已被缓冲,reference source 中甚至暗示它不应用作BufferedStream 的来源。
  • 谢谢,我不知道。那么我们可以直接将FS喂给SR。
  • 正如@Dirk 所说,FileStream 类已经被缓冲... :)
【解决方案2】:

它的 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)

【讨论】:

  • 链接已失效 :(
  • @zackraiyan - 我试过但被社区拒绝了,你能再做一次吗,我会尽快接受
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-17
  • 2019-04-30
  • 2013-05-11
  • 2016-10-10
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多