对于StringBuilder的OutOfMemoryException,将length设置为0

时间:2016-03-10 10:46:18

标签: c# asp.net stringbuilder

我有一个代码块,它获取一个文件并附加需要的数据,如下所示:

var srBuilder = new StringBuilder();
using (var file = new StreamReader(document.FullSourcePath, Encoding.ASCII))
            {
                while (!file.EndOfStream)
                {                 
                    var bytess = new char[numBytes];
                    file.ReadBlock(bytess , 0, bytess.Length);
                    srBuilder.Append(buff);
                }

                document.Document += srBuilder.ToString();  ////Exception occures here
            }

但是当文件超过200 MB时,它会抛出OutofMemoryException。

我的想法是将字符串生成器的长度设置为零,如下所示:

 while (!file.EndOfStream)
        {  
            srBuilder.Length = 0;      //// Here         
            var bytess = new char[numBytes];
            file.ReadBlock(bytess , 0, bytess.Length);
            srBuilder.Append(buff);
        }

是最佳解决方案还是其他任何需要的东西?

2 个答案:

答案 0 :(得分:3)

我不知道为什么你这么复杂。您只需要一行:

document.Document += File.ReadAllText(document.FullSourcePath, Encoding.ASCII);

如果这会引发异常,那么是的,也许你没有足够的内存。

答案 1 :(得分:2)

您的最终目标是为document.Document成员变量分配一个200 MB的ASCII文件,我假设该变量是字符串类型。

长话短说:你不能这样做,需要重新考虑你的方法。

无论如何,你的这个要求将需要400 MB的连续内存(给定字符串是char[] UTF-16字符数组,每个字符重2个字节),这几乎不可能获得32位进程,运行时抛出的OutOfMemoryException试图告诉你。

任何"技巧"你会发现它会有它的缺点。

  • 以块的形式读取文件并不重要,因为最终结果是相同的:最终的字符串仍然需要400 MB的连续内存。
  • StringBuilder' s Length设置为0,通过Google搜索" C#StringBuilder OutOfMemoryException",将使异常消失,但只会导致最后一个块要分配给document.Document的文件。可以肯定地说你也不想这样。
  • 将项目更改为仅在64位计算机上运行可能是一个选项,但很可能不会(硬件和其他依赖项),并且是一个隐藏实际问题的脏方法,这就像在一条起飞的腿上使用创可贴:你忽略了致命的设计错误。有一天,有人会给你的应用程序提供一个2 GB的文件,然后你又回到原点。

您需要流式该文件,并逐行处理。

foreach (string line in File.ReadLines(filename))
{
    // process line
}