2

所有,Append当我为固定文本文件生成单行时,我正在执行以下操作

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

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

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

笔记。此固定文本导出是在后台线程上完成的。

谢谢你的时间。

4

3 回答 3

3

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

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

那是行不通的,我非常怀疑这是你真正想做的事情。

请注意,char.NET 中的每个都是两个字节, .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)。

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

无论如何,您想在创建这样的字符串后做什么?

于 2012-11-27T18:57:47.040 回答
2

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

内存碎片可能导致这是不可能的,尤其是在使用 32 位 .NET 实现时。

于 2012-11-27T18:57:44.943 回答
1

我认为可能有更好的方法来完成您要完成的工作。据推测,这StringBuilder将被写入一个文件(这就是您的描述听起来的样子),显然,您还可能处理大型(巨大)数据库记录。

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

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

于 2012-11-27T19:14:23.143 回答