UTF-8 字符问题;我看到的不是我储存的

Trouble with UTF-8 characters; what I see is not what I stored

我试过用UTF-8,运行遇到麻烦了。

我已经尝试了很多东西;这是我得到的结果:

我做错了什么?如何修复 code?我可以恢复 数据,如果可以,如何恢复?

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

您列出了 CHARACTER SET 麻烦的五个主要案例。

最佳实践

以后最好用CHARACTER SET utf8mb4COLLATION utf8mb4_unicode_520_ci。 (管道中有更新版本的 Unicode 归类。)

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

MySQL 之外,"UTF-8" 是指所有大小编码,因此实际上与 MySQL 的 utf8mb4 相同,而不是 utf8

我将在下文中尝试使用这些拼写和大写来区分内部和外部MySQL。

应该做什么的概述

  • 将您的编辑器等设置为 UTF-8。
  • HTML 表格应以 <form accept-charset="UTF-8">.
  • 开头
  • 将您的字节编码为 UTF-8。
  • 将 UTF-8 设置为客户端使用的编码。
  • 声明 column/table CHARACTER SET utf8mb4(检查 SHOW CREATE TABLE。)
  • <meta charset=UTF-8>开头HTML
  • 存储例程获取当前 charset/collation。他们可能需要重建。

UTF-8 all the way through

More details for computer languages(及其后续部分)

测试数据

使用工具或 SELECT 查看数据是不可信的。 太多这样的客户端,尤其是浏览器,试图补偿不正确的编码,并向您显示正确的文本,即使数据库已损坏。 因此,选择一个 table 和包含一些非英语文本的列并执行

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

正确存储的 UTF-8 的 HEX 将为

  • 空白space(任何语言):20
  • 对于英语:4x5x6x7x
  • 对于西欧大部分地区,重音字母应为 Cxyy
  • 西里尔字母、希伯来字母和 Farsi/Arabic:Dxyy
  • 亚洲大部分地区:Exyyzz
  • 表情符号和一些中文:F0yyzzww
  • More details

所见问题的具体原因和修复方法

截断的 文本(Se for Señor):

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

Black Diamonds 带问号(Se�or for 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 for Señor):

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

MojibakeSeñor 对于 Señor): (此讨论也适用于 Double Encoding,不一定可见。)

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

如果数据看起来正确,但排序不正确,则 要么你选择了错误的归类, 或者没有适合您需要的排序规则, 或者你有 双重编码.

双重编码可以通过上述SELECT .. HEX ..确认。

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

也就是说,十六进制的长度大约是应有长度的两倍。 这是由于从 latin1(或其他)转换为 utf8,然后处理那些 字节,就好像它们是 latin1 并重复转换。 排序(和比较)不能正常工作,因为它是,例如, 排序就好像字符串是 Señor.

尽可能修复数据

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

对于Mojibake / 双重编码, ...

黑钻, ...

此处列出了修复。 (针对 5 种不同情况的 5 种不同修复;谨慎选择):http://mysql.rjweb.org/doc.php/charcoll#fixes_for_various_cases

  1. 将代码 IDE 语言设置为 UTF-8

  2. 添加到您收集数据表单的网页 header。

  3. 检查您的 MySQL table 定义如下:

     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 以正确的字符集导出,然后以 UTF-8 导入。

根据服务器的设置方式,您必须相应地更改编码。你所说的 utf8 应该是最好的。但是,如果您遇到奇怪的字符,将网页编码更改为 ANSI 可能会有所帮助。

这在我设置 PHP MySQLi. This might help you understand more: ANSI to UTF-8 in Notepad++

时帮助了我

在服务器迁移后,我的两个项目也遇到了类似的问题。在搜索并尝试了很多解决方案之后,我遇到了这个:

mysqli_set_charset($con,"utf8");

将此行添加到我的配置文件后,一切正常!

我为 MySQLiPHP mysqli set_charset() Function 找到了这个解决方案——当时我正在寻找解决来自 HTML 查询的插入问题。

我也在找同样的问题。我花了将近一个月的时间才找到合适的解决方案。

首先,您必须更新您的数据库,将所有最近的字符和排序规则更新为 utf8mb4 或至少支持 UTF-8 数据。

对于Java:

在建立 JDBC 连接时,将此添加到连接 URL useUnicode=yes&characterEncoding=UTF-8 作为参数,它会起作用。

对于Python:

在查询数据库之前,尝试在游标上强制执行此操作

* cursor.execute('SET NAMES utf8mb4') cursor.execute("SET CHARACTER SET utf8mb4") cursor.execute("SET character_set_connection=utf8mb4") *

如果它不起作用,请寻找正确的解决方案。