0

我想使用 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

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

我尝试了几种改变参数的不同排列:

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

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

提前致谢,

-詹姆士

4

1 回答 1

0

我一直对回应感到不知所措,但我已经破解了它。

生成loader文件需要带-wflag,所以生成文件的命令是:

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(错误地)称之为“unicode”)是双字节字符编码。

以这种方式处理 BCP 的任何其他人的理智的一些注意事项:

  • 当 SQLServer 谈到“本机”时,它们是指本机字符,即重音字符
  • 当 SQLServer 谈到 Unicode 时,它​​们的实际意思是 UTF16 (Little Endian) 编码Unicode 字符集的方式。这就是 -w 的意义所在
  • 使用 UTF-16 写入要加载到 BCP 的文件时,该文件必须采用 UTF-16 Little Endian 格式,并且不能包含 UTF BOM(因为 BCP 会将这个字节解释为应该加载的字节,并且您的第一条记录将包含BOM,呃!)

用这种方式可以加载的 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();
于 2010-02-15T15:57:54.460 回答