Почему SSIS не распознает символ перевода строки {LF} при импорте простого файла UTF-8? - PullRequest
29 голосов
/ 07 июня 2011

Я пытаюсь импортировать данные из плоского файла с кодировкой utf-8 в SQL Server 2008 с помощью служб SSIS.Вот как выглядят данные конца строки в Notepad ++:

enter image description here

У меня есть еще пара изображений, показывающих, как выглядит диспетчер соединений с файлами:

enter image description here

enter image description here

Вы можете видеть, что данные правильно отображаются в предварительном просмотре диспетчера соединений с файлами.Когда я пытаюсь импортировать эти данные, строки не импортируются.Я получаю сообщение об ошибке, указывающее, что разделитель строк не найден.В изображениях диспетчера соединений с файлами видно, что разделитель строки заголовка и разделитель строки установлены на {LF}.Этого было достаточно для создания правильного предварительного просмотра, поэтому я заблудился из-за того, что он не работал для импорта.Я пробовал несколько вещей, которые дали нулевые результаты:

  • Пробовал с помощью мастера импорта в SSMS ... те же результаты
  • Пробовал с использованием преобразования данных, без последствий
  • Попытка установки разделителя строк на (0a), те же результаты

[Flat File Source [582]] Предупреждение: конец файла данных был достигнут при чтении строк заголовка.Убедитесь, что разделитель строк заголовка и количество пропускаемых строк заголовков указаны правильно.

Спасибо за просмотр, и я очень признателен за любую помощь, которую вы можете предложить.

Ответы [ 3 ]

62 голосов
/ 07 июня 2011

Причина:

Служба SSIS не может прочитать файл и отображает следующее предупреждение из-за разделителя столбцов Ç ( "c" с cedilla ) и not из-за ограничителя строки {LF} ( перевод строки ).

[Read flat file [1]] Warning: The end of the data file was reached while 
reading header rows. Make sure the header row delimiter and the number of 
header rows to skip are correct.

Вот пример пакета служб SSIS, в котором показано, как решить проблему с помощью Script Component, а в конце - еще один пример, имитирующий вашу проблему.

Разрешение:

Ниже образец пакета написан в SSIS 2008 R2. Он читает плоский файл с разделителем строк {LF} в виде значения одного столбца; затем разделяет данные, используя Script Component, чтобы вставить информацию в таблицу в базе данных SQL Server 2008 R2.

Используйте Блокнот ++ , чтобы создать простой плоский файл с несколькими строками. В приведенном ниже примере файла Идентификатор продукта и Прайс-лист информация о каждой строке разделена Ç как разделитель столбцов, и каждая строка заканчивается {LF} разделитель.

Flat file source

В Блокноте ++ нажмите Encoding, а затем нажмите Encoding in UTF-8, чтобы сохранить плоский файл в кодировке UTF-8.

Encoding UTF-8

В примере будет использоваться база данных SQL Server 2008 R2 с именем Sora. Создайте новую таблицу с именем dbo.ProductListPrice, используя приведенный ниже скрипт. Служба SSIS вставит данные плоского файла в эту таблицу.

USE Sora;
GO

CREATE TABLE dbo.ProductListPrice
(
        ProductId   nvarchar(30)    NOT NULL
    ,   ListPrice   numeric(12,2)   NOT NULL
);
GO

Создание пакета служб SSIS с использованием Business Intelligence Development Studio (BIDS) 2008 R2 . Назовите пакет как SO_6268205.dtsx. Создайте источник данных с именем Sora.ds для подключения к базе данных Sora в SQL Server 2008 R2 .

Щелкните правой кнопкой мыши в любом месте внутри пакета и затем нажмите Variables, чтобы просмотреть панель переменных. Создайте новую переменную с именем ColumnDelimiter типа данных String в области действия пакета SO_6268205 и установите переменную со значением Ç

Package variables

Щелкните правой кнопкой мыши на Connection Managers и выберите New Flat File Connection..., чтобы создать соединение для чтения плоского файла.

Flat File Connection

На странице General редактора диспетчера соединений с плоскими файлами выполните следующие действия:

  • Установить Имя диспетчера соединений в ProductListPrice
  • Набор Описание до Flat file connection manager to read product list price information.
  • Выберите путь к плоскому файлу. У меня есть файл в пути C:\Siva\StackOverflow\Files\6268205\ProductListPrice.txt
  • Выберите {LF} из Разделитель строк заголовка
  • Проверка Column names in the first data row
  • Нажмите Columns Страница

Flat File Connection Manager Editor - General

На странице Columns редактора диспетчера соединений с плоскими файлами убедитесь, что Column delimiter пусто и отключено. Нажмите Advanced страницу.

Flat File Connection Manager Editor - Columns

На странице Advanced редактора диспетчера соединений с плоскими файлами выполните следующие действия.

  • Установите Имя на LineData
  • Убедитесь, что разделитель столбцов установлен на {LF}
  • Установите Тип данных на Unicode string [DT_WSTR]
  • Установите OutputColumnWidth в 255
  • Нажмите на страницу Preview.

Flat File Connection Manager Editor - Advanced

На странице Preview редактора диспетчера соединений с плоскими файлами убедитесь, что отображаемые данные выглядят правильно, и нажмите OK.

Flat File Connection Manager Editor - Preview

Вы увидите источник данных Sora и менеджер соединений с плоскими файлами ProductListPrice на вкладке Connection Managers в нижней части пакета.

Connection Managers

Перетащите Data Flow Task на вкладку Control Flow пакета и назовите ее File to database - Without Cedilla delimiter

Data Flow Task 1

Дважды щелкните по задаче Поток данных , чтобы переключить представление на вкладку Data Flow в пакете. Перетащите Flat File Source на вкладку Поток данных . Дважды щелкните Источник плоских файлов , чтобы открыть Flat File Source Editor.

На странице Connection Manager редактора источника плоских файлов выберите Диспетчер соединений с плоскими файлами ProductListPrice и нажмите Столбцы стр.

Flat File Source Editor - Connection Manager

На странице Columns редактора Источник плоских файлов проверьте столбец LineData и нажмите OK.

Flat File Source Editor - Columns

Перетащите Script Component на вкладку Поток данных под Источник плоских файлов , выберите Transformation и нажмите OK. Подключите зеленую стрелку от Источник плоского файла к Компонент сценария . Дважды щелкните Компонент скрипта , чтобы открыть Script Transformation Editor.

Нажмите Входные столбцы на Редактор преобразования сценариев и выберите LineData столбец. Нажмите Входы и выходы Страница.

Script Transformation Editor - Input Columns

На странице Inputs and Outputs редактора преобразования сценариев выполните следующие действия.

  • Измените имя входа на FlatFileInput
  • Измените имя выходов на SplitDataOutput
  • Выберите Выходные столбцы и нажмите Add Column. Повторите это снова, чтобы добавить еще один столбец.
  • Назовите первый столбец ProductId
  • Установите DataType столбца ProductId в Unicode string [DT_WSTR]
  • Установите Длина в 30

Script Transformation Editor - Inputs and Outputs - ProductId

На странице Inputs and Outputs редактора преобразования сценариев выполните следующие действия.

  • Назовите второй столбец ListPrice
  • Установите DataType столбца ListPrice в numeric [DT_NUMERIC]
  • Установите Точность на 12
  • Установите Шкала на 2
  • Нажмите Страница сценария , чтобы изменить сценарий

Script Transformation Editor - Inputs and Outputs - ListPrice

На странице Script редактора преобразования сценариев выполните следующие действия.

  • Нажмите кнопку с многоточием напротив ReadOnlyVariables и выберите переменную User::ColumnDelimiter
  • Нажмите Edit Script...

Script Transformation Editor - Script

Вставьте приведенный ниже C # в Редактор скриптов. Скрипт выполняет следующие задачи.

  • Используя значение разделителя столбцов Ç, определенное в переменной User :: ColumnDelimiter , метод FlatFileInput_ProcessInputRow разбивает входящее значение и присваивает его в два выходных столбца, определенных в преобразовании компонента сценария.

Код компонента сценария на C #

using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
    public override void PreExecute()
    {
        base.PreExecute();
    }

    public override void PostExecute()
    {
        base.PostExecute();
    }

    public override void FlatFileInput_ProcessInputRow(FlatFileInputBuffer Row)
    {
        const int COL_PRODUCT = 0;
        const int COL_PRICE = 1;

        char delimiter = Convert.ToChar(this.Variables.ColumnDelimiter);
        string[] lineData = Row.LineData.ToString().Split(delimiter);

        Row.ProductId = String.IsNullOrEmpty(lineData[COL_PRODUCT]) 
                            ? String.Empty 
                            : lineData[COL_PRODUCT];

        Row.ListPrice = String.IsNullOrEmpty(lineData[COL_PRICE]) 
                            ? 0 
                            : Convert.ToDecimal(lineData[COL_PRICE]);
    }
}

Script Component Code - C#

Перетащите OLE DB Destination на вкладку Поток данных . Подключите зеленую стрелку от Компонент сценария к Назначение OLE DB . Дважды щелкните OLE DB Destination , чтобы открыть OLE DB Destination Editor.

На странице Connection Manager редактора адресатов OLE DB выполните следующие действия.

  • Выберите Sora из Диспетчер соединений OLE DB
  • Выберите Table or view - fast load из Режим доступа к данным
  • Выберите [dbo].[ProductListPrice] из Имя таблицы или представления
  • Нажмите Отображения Страница

OLE DB Destination Editor - Connection Manager

Нажмите Mappings на странице Редактор адресатов OLE DB автоматически сопоставит столбцы, если имена входных и выходных столбцов совпадают. Нажмите OK.

OLE DB Destination Editor - Mappings

Поток данных * Вкладка 1548 * должна выглядеть примерно так после настройки всех компонентов.

Data Flow tab

Выполнить запрос select * from dbo.ProductListPrice в SQLServer Management Studio (SSMS) , чтобы найти количество строк в таблице.Он должен быть пустым перед выполнением пакета.

Rows in table before package execution

Выполнить пакет.Вы заметите, что пакет успешно обработал 9 строк.Плоский файл содержит 10 строк, но первая строка представляет собой заголовок с именами столбцов.

Package execution without delimiter

Выполните запрос select * from dbo.ProductListPrice на SQL ServerManagement Studio (SSMS) для поиска строк 9 , успешно вставленных в таблицу.Данные должны совпадать с данными плоского файла.

Rows in table after package execution

В приведенном выше примере показано, как вручную разбивать данные с помощью Script Component , поскольку Flat FileДиспетчер подключений обнаруживает ошибку при настройке разделителя столбцов Ç

Имитация проблемы:

В этом примере показан отдельный Диспетчер соединений с плоскими файлами настроен с разделителем столбцов Ç, который выполняется, но встречает предупреждение и не обрабатывает никаких строк.

Щелкните правой кнопкой мыши на Connection Managers и выберитеNew Flat File Connection... для создания соединения для чтения плоского файла.На странице General редактора диспетчера соединений с плоскими файлами выполните следующие действия:

  • Задать Имя диспетчера соединений ProductListPrice_Cedilla
  • Установить описание на Flat file connection manager with Cedilla column delimiter.
  • У меня есть файл в пути C:\Siva\StackOverflow\Files\6268205\ProductListPrice.txtВыберите плоский путь к файлу.
  • Выберите {LF} из Разделитель строк заголовка
  • Проверка Column names in the first data row
  • Нажмите Columns страница

Flat File Connection Manager Editor - With Cedilla - General

На странице Columns редактора диспетчера соединений с плоскими файлами , выполните следующие действия:

  • Установите Разделитель строк на {LF}
  • Поле разделителя столбцов может быть отключено.Нажмите Reset Columns
  • Установите Разделитель столбцов на Ç
  • Нажмите Advanced page

Flat File Connection Manager Editor - With Cedilla - Columns

На странице Advanced редактора диспетчера соединений с плоскими файлами выполните следующие действия:

  • Установите Имя на ProductId
  • Установите ColumnDelimiter на Ç
  • Установите DataType на Unicode string [DT_WSTR]
  • Установите Длина на 30
  • Щелкните столбец ListPrice

Flat File Connection Manager Editor - With Cedilla - Advanced - ProductId

На странице Advanced Редактор диспетчера соединений с плоскими файлами , выполните следующие действия:

  • Установите Имя на ListPrice
  • Установите ColumnDelimiter до {LF}
  • Установите DataType на numeric [DT_NUMERIC]
  • Установите Точность данных до 12
  • Установите DataScale на 2
  • Нажмите OK

Flat File Connection Manager Editor - With Cedilla - Advanced - ListPrice

Перетащите Data Flow task на вкладку Control Flow и назовите его File to database - With Cedilla delimiter.Отключите первую задачу потока данных.

Data Flow Task 2

Настройте вторую задачу потока данных с Flat File Source и OLE DB Destination

Data Flow Tab - 2

Дважды щелкните Источник плоского файла, чтобы открыть Flat File Source Editor.На странице Connection Manager редактора источника плоских файлов выберите Диспетчер соединений с плоскими файлами ProductListPrice_Cedilla и нажмите Столбцы настроить столбцы.Нажмите OK.

Flat File Source Editor - Cedilla

Выполнить пакет.Все компоненты будут отображаться зеленым цветом, чтобы указать, что процесс прошел успешно, но строки не будут обработаны.Вы можете видеть, что между Flat File Source и OLE DB Destination

Package Execution - Cedilla

нет никаких указаний Progress вкладка, и вы увидите следующее предупреждающее сообщение.

[Read flat file [1]] Warning: The end of the data file was reached while 
reading header rows. Make sure the header row delimiter and the number of 
header rows to skip are correct.

Progress Warning message

1 голос
/ 10 августа 2016

Ответ выше кажется очень сложным, просто преобразуйте окончания строк в файле

Dim FileContents As String = My.Computer.FileSystem.ReadAllText("c:\Temp\UnixFile.csv")

Dim NewFileContents As String = FileContents.Replace(vbLf, vbCrLf)

My.Computer.FileSystem.WriteAllText("c:\temp\WindowsFile.csv", NewFileContents, False, New System.Text.UnicodeEncoding)

Перефразировано с здесь

0 голосов
/ 23 октября 2016

Эта проблема также возникает, если вы пытаетесь использовать FlatFile, сгенерированный на другой платформе, такой как Unix, Mac и т. Д. Через SSIS в Windows

В таком случае все, что вам нужно сделать, это преобразовать формат файла, скажем, из UNIX в DOS с помощью команды unix2dos

unix2dos file-to-convert
...