Создайте файл на Java для загрузки в поле nvarchar в SQLServer 2005, используя BCP и UTF-16.
-
20-09-2019 - |
Вопрос
Я хочу использовать BCP для загрузки в таблицу SQL Server 2005 с полем nvarchar с использованием файла управления загрузчиком.Насколько я понимаю, SQL Server 2005 поддерживает только UTF-16 (и я считаю, что это UTF-16 LE).Файл выводится программой Java.На данный момент у меня это настроено следующим образом:
Файл загрузчика BCP в формате XML (созданный с помощью следующей команды:
bcp test_table format nul -c -x -T -f test_table.xml -S server
)Программа 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();
Затем используйте следующую команду 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 в сочетании с файлом конфигурации формата загрузчика?
Заранее спасибо,
-Джеймс
Решение
Я был буквально завален ответами, но мне удалось разобраться.
Файл загрузчика должен быть сгенерирован с помощью -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 (или просто «Юникод», как его (ошибочно) называет Microsoft) — это двухбайтовая кодировка символов.
Несколько замечаний для здравомыслия тех, кто имеет дело с BCP таким образом:
- Когда SQLServer говорит о «родных», они имеют в виду собственные символы, т.е.акцентированные символы
- Когда SQLServer говорит о Unicode, на самом деле они имеют в виду способ кодирования UTF16 (Little Endian). Набор символов Юникода.Вот к чему относится -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();