【问题标题】:Why might ReadToEnd throw an OutOfMemory exception but ReadAllText doesn't?为什么 ReadToEnd 可能会抛出 OutOfMemory 异常而 ReadAllText 不会?
【发布时间】:2011-09-16 19:00:49
【问题描述】:

我在尝试读取 ASP.net 网站中的 16MB 文本文件时遇到了 ReadToEnd 引发 OutOfMemory 异常的问题。

在调查原因时,我遇到了我正在做的 File.ReadAllText,但我并不关心如何获取文本。

但是查看ReadAllText 的文档并没有提到OutOfMemory 异常的可能性。这是为什么?它的实现方式是否与 ReadToEnd 不同,从而不太可能耗尽内存,或者如果内存不足,它是否会引发其他异常?

编辑添加代码只是为了显示我目前在做什么:

StreamReader inputFile = System.IO.File.OpenText(filename);
string cacheData = inputFile.ReadToEnd();
inputFile.Close();

有时我在第 2 行得到 OutOfMemory 异常。没有进行解析,文件只有 16M 的文本,我知道这没什么奇怪的。

重新启动 IIS 通常会修复它。但是当我收到错误时,我有 2G 的可用 RAM,IIS 可能达到了一些内部限制? w3wp.exe进程通常使用350-500M(这是Windows Server 2003上的IIS 6)

【问题讨论】:

  • 很多代码都会抛出OutOfMemoryException,不仅仅是ReadAllText...
  • @minitech:为什么?这不是关于他的代码的问题。
  • 喘息...有没有可能没有记录所有异常?
  • @spender:我只是想看看他是不是做错了;读取 16MB 文件通常不会导致计算机内存不足。
  • 添加了我的代码和问题的更多上下文,但我认为这更像是 ServerFault 的问题。

标签: c# .net file-io out-of-memory


【解决方案1】:

来自 Reflector,System.IO.File 类:

public static string ReadAllText(string path, Encoding encoding)
{
    using (StreamReader reader = new StreamReader(path, encoding))
    {
        return reader.ReadToEnd();
    }
}

就这样。

【讨论】:

  • 这可能很明显,但只是总结一下这个答案:在给定相同参数的情况下,两者都会抛出或不抛出相同的异常。
  • 但这并不能解释为什么ReadToEnd()会在操作系统本身似乎没有内存压力的情况下随机抛出异常……
  • @binki 有很多可能的原因——内存碎片、大文件、32 位 IIS,正如问题作者在下面指出的那样……这一切都取决于上下文。问题是,ReadToEnd() 怎么可能抛出异常而ReadAllText() 却没有。这说明这只是一个巧合,因为 ReadAllText() 调用 ReadToEnd() 因此如果后者抛出异常 - 它也会从前者传播出去。
  • @IvanDanilov,回顾一下并重新阅读问题和 OP 发布的代码,也许不同之处在于 ReadAllText() 正确调用 StreamReader.Dispose() 而 OP 的代码没有显示发生这种情况. StreamReader 的文档建议它拥有自己的缓冲区,我想这最终可能会使用大量内存。不幸的是,这只是猜测,这个问题很老,抱歉 xD。
【解决方案2】:

我在使用 C# Windows 窗体应用程序时遇到了同样的问题。使用设置为 64 位的目标平台构建我的应用程序解决了这个问题。

【讨论】:

    【解决方案3】:

    ReadAllText 如果您尝试读取包含太多文本而无法放入内存的文件,则会引发 OutOfMemory 异常 - 刚刚尝试过。

    【讨论】:

    • ReadToEnd 的 OutOfMemory 异常很少发生,以至于我无法在我的代码中重新创建它。问题更多地是关于为什么一个文档 OutOfMemory 作为可能的异常而另一个没有,它们是否类似地实现(ReadAllText 是否调用 ReadToEnd?)
    • @thelsdj - 正如 Tomas 上面所说,很多调用都可以生成 OutOfMemoryException。 MS 可能决定不记录可能发生这种情况的每一个案例。
    • @thelsdj:不管你信不信,文档有时是错误的或不完整的。
    • 事实上,OutOfMemoryException 可能绝对可能从您的任何代码行中抛出。可能除了稀有的受保护区域(如 finally 块)。例如,当 JIT 编译器尝试处理您的方法时 - 它可能会出现内存不足。你只是无法预测。
    • 这是真的!
    【解决方案4】:

    This post 很好地解释了为什么我遇到了最初的 OutOfMemory 错误。 32 位 Windows Server 2003 上的 IIS 6.0 只能使用大约 600-700M 的内存,尽管我有 4GB。

    将 /3GB 添加到 boot.ini 并重新启动服务器使错误消失(即使我的 IIS 内存使用量似乎并没有超出原来的水平)。

    【讨论】:

      猜你喜欢
      • 2014-06-22
      • 1970-01-01
      • 1970-01-01
      • 2021-04-28
      • 2013-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多