Crie um arquivo em Java para carregar em um campo Nvarchar no SQLServer 2005 usando o BCP e o UTF-16

StackOverflow https://stackoverflow.com/questions/2246355

Pergunta

Quero usar o BCP para carregar em uma tabela SQL Server 2005 com um campo Nvarchar usando um arquivo de controle de carregador. Pelo que entendi, o SQL Server 2005 suporta apenas o UTF-16 (e acredito que é UTF-16 LE). O arquivo está sendo produzido por um programa Java. A maneira como eu tenho atualmente configurada é a seguinte:

  1. Um arquivo de carregador BCP do formato XML (criado usando o seguinte comando:bcp test_table format nul -c -x -T -f test_table.xml -S server)

  2. Um programa Java usando o seguinte código para escrever a saída:

    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. Em seguida, usando o seguinte comando bcp:
    bcp test_table in from_java.txt -T -f test_table.xml -S server -error error.txt

O que eu recebo na tabela é ÿþá. e não áááááLittle Endian, BOM

Eu tentei algumas permutações diferentes de mudança de parâmetros:

  • Alterar a maneira como eu gero o arquivo de controle do carregador (usando -n para dados nativos em vez de -c para dados de caracteres ... acho que isso pode ter algo a ver com isso, mas não vi nenhuma melhoria nos meus dados inseridos)
  • Tentei várias formas diferentes da codificação UTF-16, incluindo Big Endian e Little Endian sem nascimento, sem sucesso
  • Tentei gerar o nascimento manualmente no arquivo enquanto leio em algum lugar que a Microsoft realmente gosta de usar informações da BOM
  • analisou a tentativa de produzir o arquivo como UCS-2 (em vez de UTF-16) como é (aparentemente) o que o BCP está realmente lendo o arquivo como
  • Tentado -w na importação do BCP, isso funciona, mas não em conjunto com um arquivo de formato de carregador (existe uma maneira de incorporar qualquer magia dizer ao BCP que o arquivo é codificado no UTF -16 no arquivo de formato?)
  • Eu posso fazê-lo funcionar se eu produzir o arquivo no Windows-1252 e especificar essa correção de codificação como um -c 1252 Opção para o BCP quando carrego o arquivo (mas não quero fazer isso, pois vou perder informações, pois o UTF-16 é um superconjunto do que pode ser representado em comparação com 1252)

Alguém conseguiu fazer com que o BCP carregue em um campo Nvarchar usando dados UTF-16 em conjunto com um arquivo de configuração de formato de carregador?

Desde já, obrigado,

-James

Foi útil?

Solução

Fiquei literalmente desapontado com as respostas, mas eu a quebrei.

O arquivo de carregador precisa ser gerado com um -w Flag, então o comando para gerar o arquivo é:

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

Isso leva a um arquivo de controle de carregador que parece um pouco diferente, você obtém entradas como:

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

Observe que o delimitador está listado como |\0|\0, os zeros correspondem ao byte extra no arquivo como UTF-16 (ou apenas "unicode" como Microsoft (erroneamente) chama) é uma codificação de caracteres de byte duplo.

Algumas notas para a sanidade de qualquer outra pessoa que lide com o BCP dessa maneira:

  • Quando o sqlserver fala de "nativo", eles significam personagens nativos, ou seja, personagens acentuados
  • Quando o sqlserver fala de unicode, o que eles realmente querem dizer é a maneira UTF16 (Little Endian) de codificar o Unicode caracteres. É isso que o -w pertence a
  • Ao escrever um arquivo para carregar no BCP usando o UTF-16, o arquivo deve estar no formato Little Endian UTF-16 e não pode conter um UTF BOM (como o BCP interpretará esse byte que deve ser carregado e seu primeiro registro conterá o nascido, urgh!)

O código Java para escrever um arquivo no UTF-16 que pode ser carregado dessa maneira é o seguinte:

    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();
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top