2011-04-05 72 views
3

我想读从我的MySQL数据库,并创建使用UTF-8字符串:'字符被转换为€™在JDBC

CREATE DATABASE april 
    DEFAULT CHARACTER SET utf8 
    DEFAULT COLLATE utf8_general_ci; 

我使用使感兴趣的表

DROP TABLE IF EXISTS `article`; 
CREATE TABLE `article` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `text` longtext NOT NULL, 
    `date_created` timestamp DEFAULT NOW(), 
    PRIMARY KEY (`id`) 
) CHARACTER SET utf8; 

如果我在MySQL命令行UTIL select * from article,我得到:

OIL sands output at Nexen’s Long Lake project dropped in February. 

然而,当我做

ResultSet rs = st.executeQuery(QUERY); 

long id = -1; 
String text = null; 
Timestamp date = null; 
while (rs.next()) { 
    text = rs.getString("text"); 
    LOGGER.debug("text=" text); 
} 

输出我得到的是:

text=OIL sands output at Nexen’s Long Lake project dropped in February. 

我得到通过我的连接:

DriverManager.getConnection("jdbc:" + this.dbms + "://" + this.serverHost + ":" + this.serverPort + "/" + this.dbName + "?useUnicode&user=" + this.username + "&password=" + this.password); 

我也试过,而不是useUnicode参数:

characterEncoding=UTF-8 
and 
characterEncoding=utf8 

我也试过了,而不是行

rs.getBytes("text"); 
String[] encodings = new String[]{"US-ASCII", "ISO-8859-1", "UTF-8", "UTF-16BE", "UTF-16LE", "UTF-16", "Latin1"}; 
for (String encoding : encodings) { 
    text = new String(temp, encoding); 
    LOGGER.debug(encoding + ": " + text); 
} 
// Which outputted: 
US-ASCII: OIL sands output at Nexen��������s Long Lake project dropped in February. 
ISO-8859-1: OIL sands output at Nexenââ¬â¢s Long Lake project dropped in February. 
UTF-8: OIL sands output at Nexen’s Long Lake project dropped in February. 
UTF-16BE: 佉䰠獡湤猠潵瑰畴⁡琠乥硥滃ꋢ芬ꉳ⁌潮朠䱡步⁰牯橥捴⁤牯灰敤⁩渠䙥扲畡特� 
UTF-16LE: 䥏⁌慳摮⁳畯灴瑵愠⁴敎數썮겂蓢玢䰠湯⁧慌敫瀠潲敪瑣搠潲灰摥椠敆牢慵祲� 
UTF-16: 佉䰠獡湤猠潵瑰畴⁡琠乥硥滃ꋢ芬ꉳ⁌潮朠䱡步⁰牯橥捴⁤牯灰敤⁩渠䙥扲畡特� 
Latin1: OIL sands output at Nexenââ¬â¢s Long Lake project dropped in February. 

我使用文件中的一些预定义的sql将字符串加载到数据库中。该文件是UTF-8编码的。

mysql -u april -p -D april < insert_articles.sql 

此文件包含行:

INSERT INTO article (text) value ("OIL sands output at Nexen’s Long Lake project dropped in February."); 

当我打印出来,我的应用程序中的文件中使用:

BufferedReader reader = new BufferedReader(new FileReader(new File("/home/path/to/file/sql_article_inserts.sql"))); 
String str; 
while((str = reader.readLine()) != null) { 
    LOGGER.debug("LINE: " + str); 
} 

我得到正确,预期输出:

LINE: INSERT INTO article (text) value ("OIL sands output at Nexen’s Long Lake project dropped in February."); 

任何帮助将亩ch赞赏。

一些系统细节: 我运行在Linux(Ubuntu的)

编辑:
*编辑,以指定OS
*编辑,以读取SQL输入文件详细输出。
*编辑指定更多关于如何将数据插入数据库。
*修改为修复代码中的错字,并澄清示例。

+0

你正在使用什么记录器? – Powerlord 2011-04-05 15:01:32

+0

LOGGER是一个实例:org.apache.log4j.Logger – barryred 2011-04-05 15:12:08

+0

不,这样做,似乎我运行UTF-8:System.getProperty(“file.encoding”)='UTF-8' – barryred 2011-04-05 16:14:38

回答

2

是否有可能你使用的编码不正确读取日志文件? windows-1252,我猜测。

UTF-8: OIL sands output at Nexen’s Long Lake project dropped in February. 

如果这出现在日志中,请执行日志文件的十六进制转储。如果数据是UTF-8,则预计序列Nexen’s变为4E 65 78 65 6E E2 80 99 73。如果其他应用程序将其读取为本机ANSI编码,则它会将其解码为Nexen’s

为了确认,你也可以转储返回值的单个字符,看他们是否在UTF-16是正确的:

//untested 
for(char ch : text.toCharArray()) { 
    System.out.printf("%04x%n", (int) ch); 
} 

我假设所有的数据都是在BMP,这样你就可以只需在Unicode charts中查找结果即可。

+0

我怀疑它是windows-1252,因为我运行的是linux(Ubuntu)。我将把这个字符串转储到HEX,然后将它发布到这里。 – barryred 2011-04-05 15:46:39

+0

re.getBytes的十六进制(“text”):4e6578656ec3a2e282ace284a273204c6f6e67204c616b652070726f6a6563742064726f7070656420696e2046656272756172792e。我发现你指定的4E6578656E,它启动:4e6578656e__c3a2e282ace284a27320 ... – barryred 2011-04-05 16:21:30

+0

因此,看起来在这种情况下它是错误的......所以来自数据库不是UTF-8。 – barryred 2011-04-05 16:22:27

0

JDBC URL中的参数只定义驱动程序应该如何与服务器进行通信。如果服务器默认不使用UTF8,那么这些参数也不会改变它。

您是否在连接后尝试执行以下SQL查询? (这应该将当前连接切换到服务器端的UTF8):

SET names utf8 
+0

在我获得连接后尝试了此操作: { Statement st = conn.createStatement(); stdccute(“SET names utf8”); } 但没有运气 - 仍然返回不正确。 如何检查服务器中的表/字段的编码? – barryred 2011-04-05 14:52:39

1

尝试将数据库本身设置为UTF-8。当创建DB:

CREATE DATABASE mydb 
    DEFAULT CHARACTER SET utf8 
    DEFAULT COLLATE utf8_general_ci; 

另见MySQL reference on connection charsetsMySQL reference on configuring charsets for applications

+0

我已经用'DEFAULT CHARACTER SET utf8'创建了数据库,并且现在用'DEFAULT COLLATE utf8_general_ci'重新创建了它,但没有运气。我将阅读这些参考文献并回复给您。 – barryred 2011-04-05 15:26:10

0

有几个字符编码涉及。

  • mysql命令行工具正在运行的终端/ cmd窗口。 (腻子?)
  • 环境在shell(bash)你正在运行你的东西。 (LC_CTYPE)
  • Mysql的内部(在表中使用):您定义了这个为UTF-8
  • 的JVM内部(总是UTF-16)
  • 由作家记录器使用使用的字符。默认(系统属性)或可能在日志框架配置中定义。
  • 您读取日志的终端/ cmd /编辑器。 (putty/bash?)

如果终端设置错误,可能是在mysql中插入了损坏的数据。 (例如,如果你的终端是iso-8859-1,你读的文件是UTF-8,例如)假设linux下,mysql应该查看env LC_CTYPE(但我不是100%确定它的确如此)。

JDBCD驱动程序负责将数据库字符编码转换为JVM的内部格式(UTF16),因此不应该成为问题。但是你可以用一个插入一个硬编码字符串的simpel java程序来测试它,然后读回它。打印原件和收到的字符串 - 它们应该是相同的。但; 如果两者都不对,您对终端字符集定义有问题。

使用像“HejÅÄÖ”的字符串一些戏剧...

此外,写一个小程序,使用一个转换为UTF-8的PrintWriter打印相同的字符串到一个文件,并验证工具,您用于读取日志打印正确的文件。如果没有,则再次怀疑终端设置。

String test = "Test HEJ \u00C5\u00C4\u00D6 ÅÄÖ"; 
// here's how to define what character set to use when writing to a fileOutputStream 
PrintWriter pw = new PrintWriter("test.txt","UTF8"); 
pw.println(test); 
pw.flush(); 
pw.close(); 
System.out.println(test); 

输出 - >测试HEJ AAO AAO

内容妮文件test.txt应该是相同的。

+0

我编辑了结果我的问题的结束,但看起来像LOGGER读正确的字符。 – barryred 2011-04-05 16:40:26

+0

另外,我可以看到它,所以终端也可以正确显示字符。 – barryred 2011-04-05 16:40:57