SQL Server JDBC: Latin1 to UTF-8



SQL Server中有一个排序规则为SQL_Latin1_General_CP1_CS_AS的表。表有一个列varchar(35),排序规则是SQL_Latin1_General_CP1_CS_AS。

列包含字符8f的字符串(十六进制).

见https://www.fileformat.info/info/unicode/char/008f/index.htm根据这个页面,这个字符转换成UTF8应该变成c28f.

当我在Java中读取该列的值并将其转换为UTF-8时,8f被替换为efbfbd. 所以8f丢失了…有点。见https://www.fileformat.info/info/unicode/char/0fffd/index.htm

public static String convertStrToHex(String str) {
byte[] getBytesFromString = str.getBytes(StandardCharsets.UTF_8);

BigInteger bigInteger = new BigInteger(1, getBytesFromString);
String convertedResult = String.format("%X", bigInteger);

return convertedResult;
}

查询表

select BadCol from MyTbl
System.out.println(convertStrToHex(resultSet.getString(1));

我得到的是EFBFBD而不是C28F。

当我声明字符串变量"u008f"并将其转换为UTF-8:

String code="u008f";
System.out.println(convertStrToHex(code);

我得到正确的C28F。

那么,为什么一个变量被正确转换,但在JDBC->RecordSet错误?

使用SQL Server 2017和2019以及JDBC: mssql和jTDS进行测试,结果相同。

我将感激任何帮助!据我所知,JDBC驱动程序是罪魁祸首。但是为什么? ?

十六进制码为8f的字符在Latin-1中不存在。这是一个无效的字符

因此,当转换为UTF-8时,它被替换为替换字符。

替换字符具有Unicode码点U+FFFD。用UTF-8编码后,它变成了EF BF BD。

你是正确的,8f不是一个有效的UTF-8字节。8f也不是有效的拉丁字符。

8f在某些Windows字符集中是有效的字符,这些字符集是ISO 8859-n字符集的超集。您的varchar值可能是Windows-1250、Windows-1251、Windows-1256或Windows-1257值。您必须根据您的用户的语言,或者不太理想的情况下,根据您的软件的默认语言做出假设。

如果可能的话,将JDBC连接设置为使用这些字符集之一。(确切地说,如何做到这一点将取决于您使用的数据库。例如,我相信MySQL允许characterEncoding=windows-1250作为JDBC URL中的查询参数。

如果不能这样做,则在从数据库读取值时自己进行转换。替换:

resultSet.getString(1)

:

new String(resultSet.getBytes(1), "windows-1250")
new String(resultSet.getBytes(1), "windows-1251")
new String(resultSet.getBytes(1), "windows-1256")
new String(resultSet.getBytes(1), "windows-1257")

Windows-1250适用于中欧和东欧。维基百科说它可以用于波兰语、捷克语、斯洛伐克语、匈牙利语、斯洛文尼亚语、塞尔维亚语、罗马尼亚语、阿尔巴尼亚语和德语文本。

Windows-1251适用于西里尔语言。维基百科说,它可以用于俄语、乌克兰语和白俄罗斯语等。

Windows-1256用于阿拉伯语。

Windows-1257适用于爱沙尼亚语、拉脱维亚语和立陶宛语。

相关内容

  • 没有找到相关文章

最新更新