C# 解析文件末尾缺少换行符的文件

C# Parsing files that are missing new line character at the end of the file

问题:解析文件末尾缺少换行符的文件的最佳方法是什么?我应该只使用 try and catch OutOfMemoryException 吗?或者,有更好的方法吗?

背景: 我正在使用 StreamReader 的 Readline() 方法解析日志文件以读取下一行。因此,基本循环结构如下所示:

while ((line = sr.ReadLine()) != null)
{
      // Parse the file
}

即使在大文件(即 > 2GB)上也能很好地工作。但是,当下一行不为 null 并且 不包含换行符时,StreamReader 只会读取空格,直到所有内存都被耗尽并抛出 OutOfMemoryException。这是处理文件末尾缺少的换行符的最佳方法吗?或者,有没有更好的方法来处理这个问题?

注意:该文件是从 IIS Exchange 服务器创建的。在没有深入了解我们的 IT 团队的情况下,该文件似乎在创建过程中被截断,导致最后一行因缺少数据而损坏。

研究: 我在 SO 上发现了一个 posting(见下文),它指的是使用 File.ReadFile。虽然它适用于缺少换行符的小得多的文件(即 < 2GB),但它仍然无法处理大文件(即 > 2GB)。

https://docs.microsoft.com/en-us/dotnet/api/system.io.file.readlines?redirectedfrom=MSDN&view=netframework-4.7.2#System_IO_File_ReadLines_System_String_

编辑

编译器在下面代码示例中的 While 行停止。问题不在于代码,而在于文件。我无法 post 我们的日志文件。但是,为了演示,请在 NotePad++ 中创建几行数据。对于文件的最后一行,删除换行符,然后删除 运行 文件。 StreamReader 将在最后一行爆炸,因为它找不到行尾。

下面是删除了所有数据内容的日志文件的副本,但时间戳和每行末尾的换行符除外。对于最后一行,我包含了数据中断之前的最后一个数据元素(端口号)。请注意最后一行缺少换行符?

这应该有效: 在尝试读取下一行之前应该检查 EndOfStream。 还添加了一些 null 检查。

while (!sr.EndOfStream)
{
  line = sr.ReadLine()?.Trim() ?? "";
  // Parse the line
}

我已经确认我们的 IT 小组的文件是错误的。发生的事情是,原来通过网络传输到我本地的过程似乎出现了问题。我重新传输文件并成功解析。还有更多的行。让我失望的是网络和本地之间的文件大小是相同的——所以我在研究过程中没有考虑重新传输文件。

文件传输过程似乎首先将已满文件分配为空文件,然后开始用数据填充它。祝你诊断出无法用标准文本编辑器(例如记事本、Notepadd++、Excel 等)打开的超大文件来查看此信息。我不得不使用 Ultra Edit,问题变得显而易见。

根据 Hans Passant 对相关问题的评论(请参阅下面的 link),StreamReader 的 Readline() 方法可以很好地处理大文件,因为它在内部处理文件系统缓存。因此,OutOfMemoryExceptions 应该不是问题。我认为这是针对内存不足的计算机而不是坏文件。

感谢大家的故障排除,对于任何打扰,我深表歉意。