【问题标题】:Read text file with lots of line in C#在 C# 中读取包含大量行的文本文件
【发布时间】:2013-10-26 06:19:48
【问题描述】:

我有一个文本文件,其中可能包含多达 100 万行,我有一个代码用于一次读取一行文件,但这需要很多时间......很多很多的时间。 c# 中是否有一种方法可以优化此过程并改善阅读效果。这是我正在使用的代码。

using(var file = new StreamReader(filePath))
{
    while((line = file.ReadLine()) != null)
     {
         //do something.
     }
}

对批量阅读这些行或改进流程有什么建议吗?

谢谢。

感谢您的所有 cmets。该问题与我使用 SmartXls 库写入 Excel 的 \do 操作有关,这导致了瓶颈。我已联系开发人员解决此问题。所有建议的解决方案都适用于其他场景。

【问题讨论】:

  • 文件有多大?您可能会受到磁盘 I/O 速度的限制。这不是一个真正的编程问题。如果有什么需要优化的地方,那可能是你的// do something.sn-p 中的神秘代码。

标签: c# .net io streamreader readline


【解决方案1】:

好吧,这段代码会更简单,如果你使用 .NET 4 或更高版本,你可以使用File.ReadLines

foreach (var line in File.ReadLines())
{
    // Do something
}

请注意,这ReadAllLines 相同,因为ReadLines 返回一个IEnumerable<string>,它懒惰地读取行,而不是一次读取整个文件。

执行时的效果将与您的原始代码大致相同(它不会提高性能) - 这只是更易于阅读。

从根本上说,如果您正在阅读一个大文件,这可能需要很长时间 - 但仅阅读一百万行不应该花费“很多很多时间”。我的猜测是,无论你用线条 做什么 都需要很长时间。您可能想要并行化,可能使用生产者/消费者队列(例如通过BlockingCollection)或TPL Dataflow,或者只使用并行LINQ、Parallel.ForEach 等。

您应该使用分析器来确定时间花费在哪里。如果您正在从一个非常慢的文件系统中读取,那么它可能真的是 正在花费时间的读取。我们没有足够的信息来指导您,但您应该能够自己缩小范围。

【讨论】:

  • 但是 OP 询问了提高性能的问题。而且这段代码和他的表现是一样的。
  • @AhmedKRAIEM:正如我在回答中所说 - 这是为了提高可读性,但它会产生相同的效果。我会在答案中放大这一点。
  • 我认为improve the reading 是指读取文件而不是代码。
  • @AhmedKRAIEM:嗯,它说“改进流程”——我想说这仍然是一种改进。不过请参阅编辑,其中确实谈论了性能。
【解决方案2】:

尝试使用streamreader,看看是否更快

string filePath = "";
string fileData = "";
using (FileStream fs = new FileStream(filePath, FileMode.Open))
{
                byte[] data = new byte[fs.Length];
                fs.Seek(0, SeekOrigin.Begin);
                fs.Read(data, 0, int.Parse(fs.Length.ToString()));
                fileData = System.Text.Encoding.Unicode.GetString(data);
}

【讨论】:

    【解决方案3】:

    您可以使用 StreamReader 的int ReadBlock(char[] buffer, int index, int count) 一次读取更多数据,而不是逐行读取。这样可以避免一次读取整个文件 (File.ReadAllLines),但允许您一次在 RAM 中处理更大的块。

    【讨论】:

      【解决方案4】:

      要提高性能,请考虑通过生成另一个线程来处理负载来执行您当前在循环中所做的任何工作。

      Parallel.ForEach(file.ReadLines(), (line) =>
      {
         // do your business
      });
      

      【讨论】:

      • 使用Parallel.ForEach 更容易编码,并且会更好地进行线程管理。它将能够智能地确定并发线程的适当数量,并且它将有效地确保不超过该数量,这与您的代码在每次达到上限时都会不断减速而不是坐在上限处不同。
      • 谢谢,Servy,我不知道 Parallel.ForEach 方法。
      • 另外,这假设工作可以并行完成,并且可以安全地并行完成。我们不知道情况是否如此,或者工作是否足够昂贵以证明并行化是合理的。
      【解决方案5】:

      如果空间不是问题..创建一个大约 1mb 的缓冲区..

      using(BufferedStream bs=new BufferedStream(File.OpenRead(path),1024*1024))
      {
           int read=-1;
           byte[] buffer=new byte[1024*1024];
           while((read=bs.Read(buffer,0,buffer.Length))!=0)
           {
                  //play with buffer
           }
      }
      

      【讨论】:

        【解决方案6】:

        您还可以使用ReadAllLines(filepath) 并将文件加载到行数组中,如下所示: string[] lines = System.IO.File.ReadAllLines(@"path");

        【讨论】:

        • 您不应该同时将那么多数据拉入内存。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-11-26
        • 2018-03-11
        • 2021-10-16
        • 2021-07-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多