[英]System.out of Memory Exception for String Builder in SSIS Script Task
我在SSIS脚本任务中使用VB脚本将标头和尾部添加到平面文件中。 代码运行良好,直到最近我遇到了一个问题,文件中的行比平时多,导致脚本任务失败,并显示错误`Error:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown. at System.String.GetStringForStringBuilder(String value, Int32 startIndex, Int32 length, Int32 capacity) at System.Text.StringBuilder.GetNewString(String currentString, Int32 requiredLength) at System.Text.StringBuilder.Append(Char[] value, Int32 startIndex, Int32 charCount) at System.IO.StreamReader.ReadToEnd() at System.IO.File.ReadAllText(String path, Encoding encoding) at System.IO.File.ReadAllText(String path)`
任何人都可以帮助我解决问题。我认为我需要使用其他与字符串相关的方法来代替“ String Builder”。 我在fileContents.Append(File.ReadAllText(Dts.Connections(“ DestinationConnection”)。ConnectionString))时遇到错误
这是我的代码:
Public Sub Main()
Dim fileContents As New StringBuilder()
Dim finalfile As String
Dim firstline As String
Dim lastline As String
Dts.VariableDispenser.LockForRead("FirstLine")
Dts.VariableDispenser.LockForRead("LastLine")
Dts.VariableDispenser.LockForRead("FileName")
firstline = CType(Dts.Variables("FirstLine").Value, String)
finalfile = CType(Dts.Variables("FileName").Value, String)
lastline= CType(Dts.Variables("LastLine").Value, String)
'Write header, then append file contents and write back out.
fileContents.AppendLine(String.Format("{0}", firstline))
fileContents.Append(File.ReadAllText(Dts.Connections("DestinationConnection").ConnectionString))
fileContents.AppendLine(String.Format("{0}", lastline))
File.WriteAllText(finalfile, fileContents.ToString())
Dts.TaskResult = ScriptResults.Success
End Sub
好吧,一个简单的方法就是避免StringBuilder
:使用File.CreateText
打开TextWriter
,写第一行,然后写File.ReadAllText(...)
,然后写最后一行。
但是,这只会节省您一些内存-它将大致减少所需的内存,因为在StringBuilder
和字符串中都不需要它(我认为现在会发生这种情况)。
更好的选择是:
Using
语句) Using
语句) 这样,即使您有大量文件,也一次只需要一小部分数据在内存中。
问题是File.ReadAllText在读取大文件时有局限性,因为整个文件都已读入内存。
您需要做的是将File.ReadAllText替换为逐行读取文件,并相应地附加它。
编辑示例:
Option Explicit
Dim oFSO, sFile, oFile, sText
Set oFSO = CreateObject("Scripting.FileSystemObject")
sFile = "your text file"
If oFSO.FileExists(sFile) Then
Set oFile = oFSO.OpenTextFile(sFile, 1)
Do While Not oFile.AtEndOfStream
sText = oFile.ReadLine
If Trim(sText) <> "" Then
fileContents.AppendLine(sText)
End If
Loop
oFile.Close
Else
WScript.Echo "The file was not there."
End If
fileContents StringBuilder可能仍然存在问题。 虽然显示的原始错误是从File.ReadAllText方法引发的。 因此,希望能达到目的。
如果没有,我只会忘记fileContents StringBuilder并写出标题。 然后逐行从文件中读取并逐行将其写出,最后写入页脚。
另一种替代方法(以及更多类似SSIS的解决方案)是创建一个数据流任务,该任务读取现有文件,通过添加了页眉和页脚的脚本组件将其通过管道传输,并将其写入文件系统。 这是SSIS 2005中的外观:
脚本组件将是一个转换,其输出的SynchronousInputID设置为False,以便它可以生成页眉和页脚行:
转换的VB源应如下所示:
Public Class ScriptMain
Inherits UserComponent
Dim headerWritten As Boolean = False
Public Overrides Sub IncomingRows_ProcessInputRow(ByVal Row As IncomingRowsBuffer)
If Not headerWritten Then
WriteHeader()
End If
OutgoingRowsBuffer.AddRow()
OutgoingRowsBuffer.theLine = Row.theLine
End Sub
Public Overrides Sub FinishOutputs()
MyBase.FinishOutputs()
WriteFooter()
End Sub
Private Sub WriteHeader()
OutgoingRowsBuffer.AddRow()
OutgoingRowsBuffer.theLine = "The First Header Line"
headerWritten = True
End Sub
Private Sub WriteFooter()
OutgoingRowsBuffer.AddRow()
OutgoingRowsBuffer.theLine = "Here's a footer line"
OutgoingRowsBuffer.AddRow()
OutgoingRowsBuffer.theLine = "Here's another one"
End Sub
End Class
这样,您就可以利用SSIS的流功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.