与UTF-8字符的麻烦; 我看到的不是我所存储的

我试图使用UTF-8并遇到麻烦。

我尝试了很多东西, 这里是我得到的结果:

  • ???? 而不是亚洲人物。 即使是欧洲文本,我也得到Se?or
  • 奇怪的胡言乱语( Señor ?),例如Señor 新浪新闻 新浪新闻
  • 黑色钻石,如塞尔。
  • 最后,我陷入了数据丢失或者至less被截断的情况: Se for Señor
  • 即使我的文字看起来不错,也没有正确sorting

我究竟做错了什么? 我如何修复代码 ? 我可以恢复数据吗?如果是这样,怎么办?

这个问题困扰着这个网站的参与者,以及其他许多人。

你已经列出了CHARACTER SET麻烦的五个主要案例。

最佳实践

outlook未来,最好使用CHARACTER SET utf8mb4COLLATION utf8mb4_unicode_520_ci 。 (在pipe道中有一个更新的Unicodesorting规则。)

utf8mb4utf8一个超集,它处理4个字节的utf8代码,这是表情符号和一些中文所需要的。

在MySQL之外,“UTF-8”是指所有大小的编码,因此有效地与MySQL的utf8mb4相同,而不是utf8

我将尝试使用这些拼写和大小写来区分内部和外部的MySQL。

该做什么的概述

  • 让你的编辑器等设置为UTF-8。
  • HTML表单应该像<form accept-charset="UTF-8">
  • 把你的字节编码为UTF-8。
  • build立UTF-8作为客户端使用的编码。
  • 将列/表声明为CHARACTER SET utf8mb4 (使用SHOW CREATE TABLE检查)
  • 在HTML开头的<meta charset=UTF-8>

UTF-8一路通过 (以前叫做“utf8”)

计算机语言的更多细节 (及其后面的部分)

testing数据

用工具或SELECT查看数据是不可信的。 太多这样的客户端,尤其是浏览器,试图补偿不正确的编码,并显示正确的文本,即使数据库被损坏。 所以,选一个非英文文本的表格和列

 SELECT col, HEX(col) FROM tbl WHERE ... 

正确存储的UTF-8的hex将是

  • 空格(使用任何语言): 20
  • 对于英语: 4x5x6x7x
  • 在西欧的大部分地区,重音字母应该是Cxyy
  • 西里尔文,希伯来文,波斯文/阿拉伯文: Dxyy
  • 亚洲大部分地区: Exyyzz
  • 表情符号和一些中文: F0yyzzww
  • 更多细节

出现问题的具体原因和解决方法

截断的文本( SeSeñor ):

  • 要存储的字节不被编码为utf8mb4。 解决这个问题。
  • 另外,请检查读取期间的连接是否为UTF-8。

有问号的黑色钻石Se or ); 其中一种情况存在:

情况1(原始字节不是 UTF-8):

  • 要存储的字节不会被编码为utf8。 解决这个问题。
  • INSERT SELECT的连接(或SET NAMES )不是utf8 / utf8mb4。 解决这个问题。
  • 另外,检查数据库中的列是否是CHARACTER SET utf8 (或utf8mb4)。

情况2(原始字节 UTF-8):

  • SELECT的连接(或SET NAMES )不是utf8 / utf8mb4。 解决这个问题。
  • 另外,检查数据库中的列是否是CHARACTER SET utf8 (或utf8mb4)。

黑钻只有在浏览器设置为<meta charset=UTF-8>时才会出现。

问号 (普通的,不是黑色的)( Se?or Señor ):

  • 要存储的字节不被编码为utf8 / utf8mb4。 解决这个问题。
  • 数据库中的列不是CHARACTER SET utf8 (或utf8mb4)。 解决这个问题。 (使用SHOW CREATE TABLE 。)
  • 另外,请检查读取期间的连接是否为UTF-8。

SeñorSeñor Señor ):(这个讨论也适用于双重编码 ,这不一定是可见的。)

  • 要存储的字节需要使用UTF-8编码。 解决这个问题。
  • INSERTingINSERTing文本时的连接需要指定utf8或utf8mb4。 解决这个问题。
  • 该列需要声明CHARACTER SET utf8 (或utf8mb4)。 解决这个问题。
  • HTML应该以<meta charset=UTF-8>开头。

如果数据看起来正确,但不能正确sorting,那么要么select了错误的sorting规则,要么没有适合您需要的sorting规则,或者使用双重编码

双编码可以通过执行上述SELECT .. HEX ..来确认。

 é should come back C3A9, but instead shows C383C2A9 The Emoji 👽 should come back F09F91BD, but comes back C3B0C5B8E28098C2BD 

也就是说,这个hex大约是它的两倍。 这是由latin1(或其他)转换为utf8引起的,然后将这些字节视为latin1并重复转换。 sorting(和比较)不能正常工作,因为它是,例如,如果string是Señor

在可能的情况下修复数据

对于截断问号 ,数据丢失。

对于Mojibake / 双重编码 ,…

对于黑钻石 ,…

(我必须在另一个问题/答案中继续。)

有趣的你如何回答你自己的问题:)

1 – 将您的代码IDE语言设置为UTF8

2 – 添加到您收集数据表单的网页标题。

3 – 检查你的MySQL表的定义如下所示:

 CREATE TABLE your_table ( ... ) ENGINE=InnoDB DEFAULT CHARSET=utf8 

4 – 如果您正在使用PDO,请确保

 $options = array(PDO::MYSQL_ATTR_INIT_COMMAND=>'SET NAMES utf8'); $dbL = new PDO($pdo, $user, $pass, $options); 

如果你已经有了一个大型的数据库,你可以尝试使用正确的字符集导出SIDU,然后用UTF8导入。 祝你好运

根据服务器的设置,您必须相应地更改编码。 utf8从你说的应该最好的工作,但是如果你得到奇怪的字符,它可能会帮助,如果你改变网页编码为Ansi。 这帮助我,当我设置一个PHP的MYSQLI这可能会帮助你了解更多https://superuser.com/questions/762473/ansi-to-utf-8-in-notepad