首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用java代码模拟mysql字符集转换?

问如何使用java代码模拟mysql字符集转换?
EN

Stack Overflow用户
提问于 2015-05-14 17:26:39
回答 1查看 171关注 0票数 0

在执行mysql client.For中的sql命令时,我使用java程序模拟字符集转换示例:

代码语言:javascript
复制
mysql> show variables like 'character%';
+--------------------------+---------------------------------------+
| Variable_name            | Value                                 |
+--------------------------+---------------------------------------+
| character_set_client     | gbk                                   |
| character_set_connection | latin1                                |
| character_set_database   | latin1                                |
| character_set_filesystem | binary                                |
| character_set_results    | gbk                                   |
| character_set_server     | utf8mb4                               |
| character_set_system     | utf8                                  |
| character_sets_dir       | /opt/mysql/server-5.6/share/charsets/ |
+--------------------------+---------------------------------------+
mysql> show create table t4\G
*************************** 1. row ***************************
   Table: t4
Create Table: CREATE TABLE `t4` (
`data` varchar(100) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
mysql> insert into t4 select '\U+1F600';
mysql> select data,hex(data) from t4;
+------+-----------+
| data | hex(data) |
+------+-----------+
| ??   | 3F3F      |

从mysql文档(https://dev.mysql.com/doc/refman/5.0/en/charset-connection.html)中,数据似乎首先从os字符集(Utf8)转换为客户端(Gbk),然后从gbk(客户端)转换为latin1(连接)。因此,基于以上理解,我编写了一个java测试程序来模拟这种看不见的转换。如下所示:

代码语言:javascript
复制
/**
* os utf-8
* character_set_client gbk
* character_set_connection latin1
* field latin1
* 
* @throws UnsupportedEncodingException 
*/
@Test
public void test_os_utf8_to_client_gbk_to_connection_latin1() throws UnsupportedEncodingException{
    String emoji = "";
    String receivedStr = new String(emoji.getBytes("utf-8"),"gbk"); //os(utf-8)-->client(gbk)
    System.out.println(receivedStr);//馃榾
    String convertedStr = new String(receivedStr.getBytes("latin1"),"latin1"); //client(gbk) --> connection(latin1)
    System.out.println(convertedStr);//??
    printHexString(convertedStr.getBytes("latin1")); //3f 3f

}

上面的代码可以得到与实际mysql操作相同的结果。我想知道这个模拟背后的原则是正确的还是碰巧是正确的?

EN

回答 1

Stack Overflow用户

发布于 2015-05-15 07:48:55

是4字节的utf8字符。在MySQL中,它需要CHARACTER SET utf8mb4,而不是utf8。(外界称它为utf8或UTF-8,但MySQL有一个区别。)

\U+1F600还说,它在utf8中将是4个字节,因为它比FFFF大。

可以在MySQL的utf8或utf8mb4中呈现馃榾。它是十六进制的E9A683 E6A6BE。

对于这两种情况,latin1都不是一个好的MySQL CHARACTER SET。它可以使用(尽管不是您尝试的方式),但这只是因为latin1无法检查字节的有效性。所有8位的值在latin1中都有一定的意义。但是,对于表情符号,您可能会获得😀,对于这对中文字符,您可能会获得馃榾。

混合使用六个character%设置简直是自找麻烦。尝试从默认设置开始,然后使用SET NAMES恰好更改其中的三个。这3个是_client、_connection和_results。

问号出现的原因是:

  • 您有utf8编码的数据(good)
  • SET NAMES latin1 in in(默认,但错误)
    • 列声明为CHARACTER SET latin1 (默认,但错误)

无法从表中检索数据。

为了做正确的事情,

  • utf8-encoded data (good)
  • establish CHARACTER SET utf8mb4
  • If utf8mb4在从客户端到服务器的连接中,
  • 检查要在网页上显示的列和/或表默认值,<meta...charset=utf-8>应该在顶部附近。

(其中两个指定了utf8mb4,因为它们与MySQL对话;另外两个是更通用的utf8。)

你提到了gbk。如果客户端中的字节被编码为"gbk",则继续本段。(我怀疑它们不是,因为Java喜欢处理Unicode,所以是utf8。)如果您已经建立了SET NAMES gbk,那么在客户端中使用gbk字节是可以的。这意味着gbk编码的字节将在表的CHARACTER SET之间进行代码转换。注意:latin1不能容纳中文字符,也不能容纳表情符号,因此CHARACER SET latin1不是一个有效的对象。CHARACTER SET gbk或utf8mb4应该可以工作。(此外,我怀疑gbk不能使用这个表情符号,所以utf8mb4可能是唯一合理的选择,而SET NAMES gbk可能无法工作。)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30233739

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档