【发布时间】:2017-10-25 03:49:38
【问题描述】:
使用 SSIS 2012。我的平面文件连接管理器我有一个分隔文件,其中行分隔符设置为 CRLF,但是当它处理文件时,我有一个包含 LF 的文本列。这导致它读取它作为导致它失败的行终止符。有什么想法吗?
【问题讨论】:
-
我误解了你的问题。我在想你的平面文件包含多行分隔符。我编辑了我的答案看看
标签: sql-server ssis etl ssis-2012 flat-file
使用 SSIS 2012。我的平面文件连接管理器我有一个分隔文件,其中行分隔符设置为 CRLF,但是当它处理文件时,我有一个包含 LF 的文本列。这导致它读取它作为导致它失败的行终止符。有什么想法吗?
【问题讨论】:
标签: sql-server ssis etl ssis-2012 flat-file
我没有 SSIS 经验,但作为一名 ETL 开发人员,我遇到过很多次。因此,我的建议可能无法帮助您解决问题,但希望为您指明正确的方向
【讨论】:
在回答之前,我不认为该列只包含LF,因为如果行分隔符是CRLF,它不会将其视为分隔符。所以可能是CRLF,但是我会针对这两种情况(CRLF 或 LF)给出一个解决方案
您可以通过以下步骤解决此问题:
DT_STR,长度为4000),以便将每一行视为一列。我会考虑一个包含以下内容的平面文件
ID;name;DOB;Notes;ClassID{CRLF}
1;John;2001-01-01;;1{CRLF}
2;Moh;2002-01-01;Very cool{LF}
Genius;2{CRLF}
3;Ali;2000-01-01;Calm;2{CRLF}
在 DataFlow 任务中,我将添加一个 Flat File Source, 2 x Script Component , OLEDB Destination
在第一个脚本组件中,我将Column0 标记为输入,我将添加5 个输出列ID,Name,DOB,Notes,ClassID,并将输出同步输入设置为None
在第一个脚本组件中,我将编写一个脚本,将每一行存储在内存变量中,并在行完成且存在另一行时将其分配给输出行。
Dim strLine As String = String.Empty
Dim strDelimiter As String = ";"
Public Sub EmptyMemoryVariables()
strLine = String.Empty
End Sub
Public Sub AssignMemoryVariablesToOutput()
With Output0Buffer
.AddRow()
.NewRow = strLine
End With
End Sub
Public Function AreVariablesEmpty() As Boolean
If strLine = "" Then
Return True
Else
Return False
End If
End Function
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
Dim strColumns As String() = Row.Column0.Split(CChar(strDelimiter))
If strColumns.Length = 5 Then
If Not AreVariablesEmpty() Then
AssignMemoryVariablesToOutput()
EmptyMemoryVariables()
End If
strLine = Row.Column0
AssignMemoryVariablesToOutput()
EmptyMemoryVariables()
Else
If strLine.Split(CChar(strDelimiter)).Length = 5 Then
AssignMemoryVariablesToOutput()
EmptyMemoryVariables()
End If
strLine &= Row.Column0
End If
在第二个脚本组件中,我会将每一行拆分为列
Dim strDelimiter As String = ";"
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
Dim strColumns As String() = Row.NewRow.Split(CChar(strDelimiter))
Row.ID = strColumns(0)
Row.NAME = strColumns(1)
Row.DOB = strColumns(2)
Row.NOTES = strColumns(3)
Row.CLASSID = strColumns(4)
End Sub
重要提示:提供的代码不是最优的,它可能需要更多验证,或者可以更简单更好,但我试图为您提供解决此问题的方法
【讨论】:
感谢您的所有建议。原来供应商已将文件的编码从 Ascii 更改为 unicode。更改包以读取正确的编码就可以了。
【讨论】:
在您的平面文件连接管理器组件中,您有一个我忘记了它的名称的属性,您可以在其中设置行分隔符({CR}{LF}、{LF}、{CR}、...等)。
请尝试调整此属性,我认为它会起作用。
【讨论】:
我遇到了类似的问题。我有一个以 LF 作为终止符的 CSV 文件。但是,客户端在其中两列中也有 CRLF,这导致“未找到列的分隔符”错误。
我花了几天时间在谷歌上搜索解决方案并反复试验,但我得到了它的工作。
最后,我需要两个脚本组件。
在第一个脚本组件中,我有一个名为 Output0 字符串的列,长度为 4000。在脚本中(见下文),我使用 ReadToEnd 加载数据,将 CRLF 替换为空字符串,然后拆分为行LF 作为终止符。
using System.IO;
using System.Text;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
private StreamReader textReader;
private string collateralFile;
public override void AcquireConnections(object Transaction)
{
IDTSConnectionManager100 connMgr = this.Connections.Collateral;
collateralFile = (string)connMgr.AcquireConnection(null);
}
public override void PreExecute()
{
base.PreExecute();
}
public override void CreateNewOutputRows()
{
StreamReader textReader = new StreamReader(collateralFile);
string collatFile = textReader.ReadToEnd();
collatFile = collatFile.Replace("\r\n", " ");
String[] lines = collatFile.Split(new char[] { '\n' });
textReader.Close();
string nextLine;
for (int i = 0; i < lines.Length; i++)
{
if (lines[i] != null)
{
nextLine = lines[i];
if (!String.IsNullOrEmpty(nextLine))
{
Output0Buffer.AddRow();
Output0Buffer.Output0 = nextLine;
}
}
}
}
}
我尝试再次将其拆分为列,但它返回空值,因此在第二个脚本组件中我创建了列并将数据加载到脚本中。
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
String[] columns = Row.Output0.Split(',');
Row.Description = columns[0];
Row.LegalDescription = columns[1];
Row.Address1ParsedLine1 = columns[2];
Row.Address1ParsedLine2 = columns[4];
Row.Address1ParsedCityname = columns[5];
Row.Address1ParsedStatecode = columns[6];
Row.Address1ParsedPostalcode = columns[7];
}
【讨论】: