使用Java创建一个文件,以便使用BCP和UTF-16加载到SQLServer 2005中的nvarchar字段中

时间:2010-02-11 17:42:47

标签: sql-server bcp utf-16 nvarchar utf

我想使用BCP加载到带有nvarchar字段的SQL Server 2005表中,使用加载程序控制文件。据我了解,SQL Server 2005只支持UTF-16(我相信它是UTF-16 LE)。该文件由Java程序输出。我目前设置的方式如下:

  1. XML格式BCP加载程序文件(使用以下命令创建: 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

  4. 我在表中得到的是ÿþá。而不是áááááLittle Endian, BOM

    我尝试了一些不同的更改参数排列:

    • 更改生成加载程序控制文件的方式(对于本机数据使用-n而不是使用-c作为字符数据...我认为这可能与它有关,但我没有看到任何改进插入数据)
    • 尝试了几种不同形式的UTF-16编码,包括big endian和little endian,没有BOM,但无济于事
    • 尝试在文件中手动输出BOM,因为我读到了Microsoft真正喜欢使用BOM信息的地方
    • 试图将文件输出为UCS-2(而不是UTF-16),因为(显然)BCP实际上正在读取文件
    • 在bcp导入上尝试了-w,这确实有效,但是没有与加载器格式文件一起使用(有没有办法将任何魔法告诉BCP文件以UTF-16编码到格式文件中?)
    • 如果我在windows-1252中输出文件并在加载文件时将代码页指定为bcp的-c 1252选项,我可以使用它(但我不想这样做,因为我会正在失去信息,因为与1252相比,UTF-16是可以代表什么的超集。

    是否有人设法使用UTF-16数据和加载器格式配置文件将bcp加载到nvarchar字段中?

    提前致谢,

    -James

1 个答案:

答案 0 :(得分:0)

我对答案一直不知所措,但我已经破解了它。

需要使用-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时,它们实际上意味着编码 Unicode characterset 的UTF16(Little Endian)方式。这就是-w属于
  • 的内容
  • 当使用UTF-16编写要加载到BCP的文件时,该文件必须采用UTF-16 Little Endian格式,并且不能包含UTF BOM(因为BCP会将此字节解释为应加载的字节和您的第一个记录将包含BOM,urgh!)

以UTF-16写出可以这种方式加载的文件的Java代码如下:

    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();