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

Я хочу использовать 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 вместе с файлом конфигурации формата загрузчика?

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

-Джеймс

1 Ответ

0 голосов
/ 15 февраля 2010

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

Файл загрузчика должен быть создан с флагом -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 (ошибочно) называет это) является двухбайтовой кодировкой символов.

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

  • Когда 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();
...