【问题标题】:C# Very Large String Manipulation (Out of Memory Exception)C# 非常大的字符串操作(内存不足异常)
【发布时间】:2011-05-09 22:08:20
【问题描述】:

我需要从磁盘读取 1gb 原始文本文件到内存中,以便在 C# 中进行一些字符串操作。

string contents = File.ReadAllText(path)

正在抛出内存不足异常(不足为奇)

最好的方法是什么?

【问题讨论】:

  • 什么样的字符串操作?在任何给定时间只阅读部分内容可以吗?
  • 理论上是的,但是使用遗留代码工作,而且我知道这将被使用的环境,并且一口气阅读它会更容易。
  • 我假设您在尝试此操作的 PC 上实际上有足够的可用 RAM。我知道修改遗留代码可能会很痛苦(如果它的任务关键,也会很可怕),但您可能需要考虑一次只读取一个块并以这种方式处理它。

标签: c# string file-io


【解决方案1】:

还可以考虑使用memory-mapped file

【讨论】:

【解决方案2】:

如果你真的想在内存中进行这种巨大的字符串操作,那么只要你能满足以下要求,你就不会不走运了

  1. 编译目标 x64
  2. 在 x64 系统中运行
  3. 目标 .NET 4.5

这将解除您面临的所有内存限制。您的进程内存将仅受计算机内存的限制,从 .NET 4.5 for x64 开始,单个 .NET 对象没有 2GiB 限制。

【讨论】:

    【解决方案3】:
    【解决方案4】:

    我对 109 mb 文件使用 ReadAllText,但内存不足,这真的很奇怪。无论如何,所以我使用缓冲区来读取性能良好的文件,并使用 StringBuilder 来提高内存效率。 这是我的代码:

                    StringBuilder sb = new StringBuilder();
                    using (FileStream fs = File.Open(filePath, 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)
                            sb.AppendLine(line);
                    }
    

    【讨论】:

    • Stringbuilder 也会抛出该大小的内存不足异常。见this question
    • 不要将 StreamReader 与 BufferedStream 一起使用!使用 BufferedStream 是多余的。因为缓冲机制几年前已经在.Net中实现了。你最终有两个缓冲区。看看这个stackoverflow.com/a/2069317/81306
    【解决方案5】:

    如果其他人建议的解决方案不起作用,我建议您设置阅读字符的限制,并分部分阅读文本。一旦缓存了部分文本,就可以对其进行操作。

    如果您需要在任何方向操作它(我的意思是,不是一步从左到右),您始终可以实现 B-Tree 并将部分文本存储在节点中:)

    有时,按顺序逐段阅读文本几乎是不可能的,这就是 B-Tree 的帮助所在。大约一年前,我出于学术目的(小型数据库管理器)实现了它,但我认为应该在 C# 中实现它。当然,你必须实现如何从文件中加载 BTree 的节点。

    【讨论】:

      猜你喜欢
      • 2012-02-03
      • 1970-01-01
      • 2012-01-23
      • 1970-01-01
      • 2011-02-20
      • 1970-01-01
      • 2016-07-27
      • 2010-09-17
      相关资源
      最近更新 更多