StringBuilder与PadLeft / Right OutOfMemoryException一起使用

时间:2012-11-27 18:56:33

标签: c# stringbuilder string-concatenation

全部,当我为固定文本文件生成单行时,我正在执行以下Append

formattedLine.Append(this.reversePadding ?
                     strData.PadLeft(this.maximumLength) :
                     strData.PadRight(this.maximumLength)); 

此特殊异常发生在PadLeft() this.maximumLength = 1,073,741,823 [从SQL Server收集的NVARCHAR(MAX)的字段长度]中。在例外时formattedLine = "101102AA-1",为什么会发生这种情况。我的最大允许长度应为2,147,483,647

我想知道https://stackoverflow.com/a/1769472/626442是否在这里作为答案 - 但是,我正在管理任何内存,并在可能的情况下对任何一次性对象和Dispose()块进行适当的using调用。

请注意。此固定文本导出正在后台线程上完成。

感谢您的时间。

3 个答案:

答案 0 :(得分:3)

  

这个特殊异常发生在PadLeft()上,其中this.maximumLength = 1,073,741,823

右。因此,您正在尝试创建一个包含超过十亿个字符的字符串。

这不会起作用,而且非常非常怀疑这是你真正想做的事情。

请注意,.NET中的每个char都是两个字节,而.NET中的也是字符串是以空值终止的...并且还有一些超出数据的其他字段(长度,一个)。这意味着您至少需要2147483652个字节+对象开销,这会使您超过每个对象2GB的限制。

如果你在64位版本的Windows上运行,在.NET 4.5中,有一个特殊的app.config设置<gcAllowVeryLargeObjects>允许大于2GB的数组。但是,我不相信这会改变您的特定用例:

  

在应用程序配置文件中使用此元素可以启用大小超过2 GB的数组,但不会更改对象大小或数组大小的其他限制:

     
      
  • 数组中的最大元素数是UInt32MaxValue。

  •   
  • 对于字节数组和单字节结构数组,任何单个维度的最大索引为2,147,483,591(0x7FFFFFC7),其他类型为2,146,435,071(0X7FEFFFFF)。

  •   
  • 字符串和其他非数组对象的最大大小不变。

  •   

无论如何,你想在创建它后用这个字符串做什么?

答案 1 :(得分:2)

为了为此操作分配内存,操作系统必须找到足够大的连续内存来执行操作。

内存碎片可能导致这种情况无法实现,尤其是在使用32位.NET实现时。

答案 2 :(得分:1)

我认为可能有更好的方法来实现您想要实现的目标。据推测,这个StringBuilder将被写入文件(这就像你的描述中所说的那样),显然,你也可能处理大型(巨大的)数据库记录。

你可能会考虑一种流媒体方法,它不需要分配如此庞大的内存块。 为此,您可以调查以下内容:

SqlDataReader类公开了GetChars()方法,允许您读取单个大型记录的大块。 然后,不是使用StringBuilder,而是使用StreamWriter(或其他TextWriter派生类)将每个块写入输出。 这只需要在应用程序的内存空间中一次填充一个缓冲区。祝你好运!