SSIS - плоский файл всегда ANSI, никогда не кодируется в UTF-8 - PullRequest
17 голосов
/ 16 марта 2011

Иметь довольно простой пакет служб SSIS:

  • Источник OLE DB для получения данных через представление (все строковые столбцы в таблице db nvarchar или nchar).
  • Производный столбец для форматирования существующей даты и добавления ее в набор данных (тип данных DT_WSTR).
  • Многоадресная задача для разделения набора данных между:
    • OLE DB Команда для обновления строк как «обработанных».
    • Назначение плоского файла - для диспетчера соединений которого установлена ​​кодовая страница 65001 UTF-8, а Unicode не проверен. Все строковые столбцы отображаются в DT_WSTR.

Каждый раз, когда я запускаю этот пакет, откройте плоский файл в Notepad ++, его ANSI, а не UTF-8. Если я проверю опцию Unicode, файл будет UCS-2 Little Endian.

Я что-то не так делаю - как мне получить плоский файл в кодировке UTF-8?

Спасибо

Ответы [ 4 ]

24 голосов
/ 16 мая 2012

В источнике -> Расширенный редактор -> Свойства компонента -> Установите значение по умолчанию для Кодовой страницы 65001 AlwaysUseDefaultCodePage в значение True

Затем выберите Источник -> Расширенный редактор -> Свойства ввода и вывода Проверьте каждый столбец во внешних столбцах и OutPutСтолбцы и установите CodePage на 65001, где это возможно.

Вот и все.

Кстати, Excel не может определить данные внутри файла как UTF - 8. Excel - это просто обработчик файла.Вы также можете создавать CSV-файлы с помощью блокнота.до тех пор, пока вы заполняете CSV-файл UTF-8, все будет в порядке.

5 голосов
/ 06 февраля 2014

Добавление объяснения к ответам ...

установка CodePage на 65001 (но НЕ проверять флажок Unicode в источнике файла), должен генерировать файл UTF-8. (да, внутренне типы данных также должны быть nvarchar и т. д.).

Но файл, созданный из SSIS, не имеет заголовка BOM (Byte Order Marker), поэтому некоторые программы предполагают, что это все еще ASCII, а не UTF-8. Я видел это подтвержденное сотрудниками MS на MSDN , а также подтвержденное тестированием.

Решение для добавления файлов позволяет обойти это - создав пустой файл с соответствующей спецификацией, а затем добавив данные из служб SSIS, заголовок спецификации остается на месте. Если вы указываете SSIS перезаписать файл, он также теряет спецификацию.

Спасибо за подсказки, это помогло мне разобраться в вышеперечисленных деталях.

4 голосов
/ 09 апреля 2015

Я недавно работал над проблемой, когда мы сталкиваемся с такой ситуацией:

Вы работаете над решением, использующим службы интеграции SQL Server (Visual Studio 2005). Вы извлекаете данные из своей базы данных и пытаетесь поместить результаты в плоский файл (.CSV) в формате UTF-8. Решение отлично экспортирует данные и сохраняет специальные символы в файле, потому что вы использовали 65001 в качестве кодовой страницы.

Тем не менее, текстовый файл, когда вы открываете его или пытаетесь загрузить его в другой процесс, он говорит, что файл ANSI вместо UTF-8. Если вы откроете файл в блокноте и сделаете SAVE AS и измените кодировку на UTF-8, то ваш внешний процесс заработает, но это утомительная ручная работа.

То, что я обнаружил, что когда вы указываете свойство Code Page диспетчера соединений с плоскими файлами, оно генерирует файл UTF-8. Однако он генерирует версию файла UTF-8, в которой отсутствует то, что мы называем Порядком байтов.

Таким образом, если у вас есть файл CSV, содержащий символ AA, спецификация для UTF8 будет 0xef, 0xbb и 0xbf. Несмотря на то, что файл не имеет спецификации, он все еще в формате UTF8.

К сожалению, в некоторых старых устаревших системах приложения ищут спецификацию, чтобы определить тип файла. Похоже, что ваш процесс тоже делает то же самое.

Чтобы обойти эту проблему, вы можете использовать следующий фрагмент кода в своей задаче скрипта, который можно запустить после процесса экспорта.

using System.IO;

using System.Text;

using System.Threading;

using System.Globalization;

enter code here

static void Main(string[] args)
       {
           string pattern = "*.csv";
           string[] files = Directory.GetFiles(@".\", pattern, SearchOption.AllDirectories);
           FileCodePageConverter converter = new FileCodePageConverter();
           converter.SetCulture("en-US");
           foreach (string file in files)
           {
               converter.Convert(file, file, "Windows-1252"); // Convert from code page Windows-1250 to UTF-8  
           }  
       }

class FileCodePageConverter 
  { 
      public void Convert(string path, string path2, string codepage) 
      { 
          byte[] buffer = File.ReadAllBytes(path); 
          if (buffer[0] != 0xef && buffer[0] != 0xbb) 
          { 
              byte[] buffer2 = Encoding.Convert(Encoding.GetEncoding(codepage), Encoding.UTF8, buffer); 
              byte[] utf8 = new byte[] { 0xef, 0xbb, 0xbf }; 
              FileStream fs = File.Create(path2); 
              fs.Write(utf8, 0, utf8.Length); 
              fs.Write(buffer2, 0, buffer2.Length); 
              fs.Close(); 
          } 
      } 

      public void SetCulture(string name) 
      { 
          Thread.CurrentThread.CurrentCulture = new CultureInfo(name); 
          Thread.CurrentThread.CurrentUICulture = new CultureInfo(name); 
      } 
  }

когда вы запустите пакет, вы обнаружите, что все файлы CSV в указанной папке будут преобразованы в формат UTF8, который содержит метку порядка байтов.

Таким образом, ваш внешний процесс сможет работать с экспортированными файлами CSV.

если вы ищете только определенную папку ... отправьте эту переменную в задачу скрипта и используйте ниже одной ..

      string sPath;

      sPath=Dts.Variables["User::v_ExtractPath"].Value.ToString();

      string pattern = "*.txt";

      string[] files = Directory.GetFiles(sPath);

Надеюсь, это поможет !!

0 голосов
/ 02 апреля 2011

ОК - похоже, нашел приемлемый обходной путь на форумах SQL Server .По сути, мне пришлось создать два файла шаблона UTF-8, использовать задачу «Файл», чтобы скопировать их в место назначения, а затем убедиться, что я добавляю данные, а не перезаписываю.

...