【问题标题】:SSIS reading LF as terminator when its set as CRLF当设置为 CRLF 时,SSIS 将 LF 读取为终止符
【发布时间】:2017-10-25 03:49:38
【问题描述】:

使用 SSIS 2012。我的平面文件连接管理器我有一个分隔文件,其中行分隔符设置为 CRLF,但是当它处理文件时,我有一个包含 LF 的文本列。这导致它读取它作为导致它失败的行终止符。有什么想法吗?

【问题讨论】:

  • 我误解了你的问题。我在想你的平面文件包含多行分隔符。我编辑了我的答案看看

标签: sql-server ssis etl ssis-2012 flat-file


【解决方案1】:

我没有 SSIS 经验,但作为一名 ETL 开发人员,我遇到过很多次。因此,我的建议可能无法帮助您解决问题,但希望为您指明正确的方向

  • 如果问题字段有文本限定符(单引号或双引号 通常)并且 SSIS 支持使用它
  • 如果有选项 强制 SSIS 使用除 LF 以外的不同的记录结尾分隔符(在这种情况下为 CRLF)我会使用它(希望问题字段文本中没有 CRLF)
  • 如果问题字段不是最后一个字段,您可以通过将整条记录读取为单个 LF 分隔字段来计算分隔符的数量 识别并过滤掉问题记录(如果只有少数) 并尝试将它们缝合起来
  • 如果可能,将文件作为单个文件读取 记录(如果 SSIS 有选项)并替换所有 LF,前提是 CR 来自源的一致的记录结束分隔符

【讨论】:

    【解决方案2】:

    在回答之前,我不认为该列只包含LF,因为如果行分隔符是CRLF,它不会将其视为分隔符。所以可能是CRLF,但是我会针对这两种情况(CRLF 或 LF)给出一个解决方案

    解决方案

    您可以通过以下步骤解决此问题:

    1. 首先在平面文件连接管理器中只添加一列(类型为DT_STR,长度为4000),以便将每一行视为一列。
    2. 在数据流任务中,您必须添加一个脚本组件来修复文件结构。并将行拆分为列。

    简单测试

    我会考虑一个包含以下内容的平面文件

    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}
    
    1. 首先,我将添加一个带有以下选项的平面文件连接管理器:
      • 行分隔符 = {CRLF}
      • 标题行分隔符 = {CRLF}

    1. 在 DataFlow 任务中,我将添加一个 Flat File Source, 2 x Script Component , OLEDB Destination

    2. 在第一个脚本组件中,我将Column0 标记为输入,我将添加5 个输出列ID,Name,DOB,Notes,ClassID,并将输出同步输入设置为None

    1. 在第一个脚本组件中,我将编写一个脚本,将每一行存储在内存变量中,并在行完成且存在另一行时将其分配给输出行。

      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
      
    2. 在第二个脚本组件中,我会将每一行拆分为列

        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
    

    重要提示:提供的代码不是最优的,它可能需要更多验证,或者可以更简单更好,但我试图为您提供解决此问题的方法

    【讨论】:

    • 这行不通,因为 OP 声明额外的 LF 在列中,这对我来说意味着读者此时停止阅读该行。从末端删除 CR 不会有任何改变,因为它仍然会为那些在列中包含 LF 字符的行读取额外的错误行。
    • 感谢您的评论。我误解了这个问题。我会改变我的答案。非常感谢
    【解决方案3】:

    感谢您的所有建议。原来供应商已将文件的编码从 Ascii 更改为 unicode。更改包以读取正确的编码就可以了。

    【讨论】:

    • 只要接受这个答案,即使它是你的,所以问题被标记为已回答。提供的答案也很有帮助,这些人会花时间解决你的问题,所以很高兴在那里投票
    【解决方案4】:

    在您的平面文件连接管理器组件中,您有一个我忘记了它的名称的属性,您可以在其中设置行分隔符({CR}{LF}{LF}{CR}、...等)。

    请尝试调整此属性,我认为它会起作用。

    【讨论】:

    • 这不是真的!我在上一份工作中经常使用SSIS,但我现在的工作中没有它,所以我无法检查财产,我回答了。我认为当有人试图提供帮助并且不要给出错误答案时投反对票不是一个好主意,顺便说一句,这只是我的选择。我真的不知道其他答案如何,请您告知一下吗?我认为拥有另一个遮阳篷是很常见的
    【解决方案5】:

    我遇到了类似的问题。我有一个以 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];
    }
    

    【讨论】:

      猜你喜欢
      • 2017-03-21
      • 2016-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-12
      相关资源
      最近更新 更多