Создайте файл на Java для загрузки в поле nvarchar в SQLServer 2005 с использованием BCP и UTF-16

Я хочу использовать BCP для загрузки в таблицу SQL Server 2005 с полем nvarchar с использованием файла управления загрузчиком. Насколько я понимаю, SQL Server 2005 поддерживает только UTF-16 (и я считаю, что это UTF-16 LE). Файл выводится программой Java. В настоящее время я настроил его следующим образом:

  1. Файл загрузчика BCP в формате XML (создается с помощью следующей команды: bcp test_table format nul -c -x -T -f test_table.xml -S server)

  2. Программа Java, использующая следующий код для записи вывода:

    File f = new File("from_java.txt");
    String encoding = "x-UTF-16LE-BOM";
    OutputStream os = new FileOutputStream(f);
    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(os, encoding);
    String theString = "áááááLittle Endian, BOM\r\n";
    outputStreamWriter.append(theString);
    outputStreamWriter.flush();
    outputStreamWriter.close();
    
  3. Затем с помощью следующей команды bcp:
    bcp test_table in from_java.txt -T -f test_table.xml -S server -error error.txt

В таблице я вижу ÿþá. а не áááááLittle Endian, BOM

Я пробовал несколько разных вариантов изменения параметров:

  • изменение способа создания файла управления загрузчиком (использование -n для собственных данных вместо -c для символьных данных ... Я думаю, что это может иметь какое-то отношение к этому, но я не заметил никаких улучшений во вставленных данных)
  • пробовал несколько разных форм кодировки UTF-16, включая прямой порядок байтов и прямой порядок байтов без спецификации, безрезультатно
  • пытался вывести спецификацию вручную в файл, поскольку я где-то читал, что Microsoft действительно любит использовать информацию о спецификации
  • рассмотрел попытку вывести файл как UCS-2 (вместо UTF-16), поскольку это (по-видимому) то, что BCP на самом деле читает файл как
  • попробовал -w для импорта bcp, это работает, но не в сочетании с файлом формата загрузчика (есть ли способ включить магию, сообщающую BCP, что файл закодирован в UTF-16 в файл формата?)
  • Я могу заставить его работать, если я выведу файл в windows-1252 и укажу эту кодовую страницу как параметр -c 1252 для bcp при загрузке файла (но я не хочу этого делать, так как я буду терять информацию как UTF-16 это надмножество того, что можно представить по сравнению с 1252)

Кому-нибудь удалось заставить bcp загрузить в поле nvarchar с использованием данных UTF-16 в сочетании с файлом конфигурации формата загрузчика?

Заранее спасибо,

-Джеймс


person James B    schedule 11.02.2010    source источник


Ответы (1)


Я был буквально потрясен ответами, но я взломал их.

Файл загрузчика должен быть сгенерирован с флагом -w, поэтому команда для создания файла:

bcp <table> format nul -w -x T -f loader-control-w-format.xml -S <server> -t "||"

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

<FIELD ID="1" xsi:type="NCharTerm" TERMINATOR="|\0|\0" MAX_LENGTH="1000" COLLATION="SQL_Latin1_General_CP1_CI_AS"/>

Обратите внимание, что разделитель указан как |\0|\0, нули соответствуют дополнительному байту в файле, поскольку UTF-16 (или просто «unicode», как Microsoft (ошибочно) называет его) - это двухбайтовая кодировка символов.

Некоторые примечания для здравомыслия любого, кто имеет дело с BCP таким образом:

  • Когда SQLServer говорит о «родном», они имеют в виду родные символы, то есть символы с диакритическими знаками.
  • Когда SQLServer говорит о Unicode, на самом деле они имеют в виду способ кодирования в формате UTF16 (Little Endian) набора символов Unicode. Это то, к чему относится -w
  • При записи файла для загрузки в BCP с использованием UTF-16 файл должен быть в формате UTF-16 Little Endian и не может содержать спецификацию UTF (поскольку BCP интерпретирует это как байт, который должен быть загружен, и ваша первая запись будет содержать спецификация, срочно!)

Код Java для записи файла в UTF-16, который можно загрузить таким образом, выглядит следующим образом:

    final File f = new File("C:\\temp\\bcp_prob\\from_java-UTF-16.txt");
    //LE with no BOM is important here:
    final String encoding = "UTF-16LE";
    final OutputStream os = new FileOutputStream(f);
    final OutputStreamWriter outputStreamWriter = new OutputStreamWriter(os, encoding);
    final String theString = "UTF-16-LE, intermetálico básicos intermetálico película magnética dinámicos||another_col\r\n";        
    outputStreamWriter.append(theString);
    outputStreamWriter.flush();
    outputStreamWriter.close();
person James B    schedule 15.02.2010