提问人:Rick James 提问时间:7/14/2016 最后编辑:Peter MortensenRick James 更新时间:6/14/2023 访问量:102694
UTF-8 字符问题;我看到的不是我存储的
Trouble with UTF-8 characters; what I see is not what I stored
问:
我尝试使用UTF-8并遇到了麻烦。
我尝试了很多方法;以下是我得到的结果:
????
而不是亚洲字符。即使是欧洲文本,我也得到了.Se?or
Señor
- 奇怪的胡言乱语(Mojibake?),例如 or for .
Señor
新浪新闻
新浪新闻
- 黑色钻石,如硒或。
- 最后,我遇到了数据丢失或至少被截断的情况:for .
Se
Señor
- 即使我让文本看起来正确,它也没有正确排序。
我做错了什么?如何修复代码?我可以恢复数据吗,如果可以,如何恢复?
答:
这个问题困扰着本网站的参与者以及许多其他人。
您列出了五种主要的麻烦情况。CHARACTER SET
最佳实践
展望未来,最好使用 和 .(管道中有一个较新版本的 Unicode 排序规则。CHARACTER SET utf8mb4
COLLATION utf8mb4_unicode_520_ci
utf8mb4
是 的超集,因为它处理 4 字节的 utf8 代码,这是 Emoji 和一些中文需要的。utf8
在MySQL之外,“UTF-8”指的是所有大小的编码,因此实际上与MySQL的相同,而不是。utf8mb4
utf8
在下文中,我将尝试使用这些拼写和大小写来区分MySQL内部和外部。
您应该采取的措施概述
- 将编辑器等设置为 UTF-8。
- HTML 表单应以 .
<form accept-charset="UTF-8">
- 将字节编码为 UTF-8。
- 将 UTF-8 建立为客户端中使用的编码。
- 声明列/表(使用 .
CHARACTER SET utf8mb4
SHOW CREATE TABLE
<meta charset=UTF-8>
在 HTML 的开头- 存储例程获取当前字符集/排序规则。他们可能需要重建。
计算机语言(及其以下部分)的更多详细信息
测试数据
使用工具或 不可信地查看数据。
太多这样的客户端,尤其是浏览器,试图补偿不正确的编码,并显示正确的文本,即使数据库被破坏了。
因此,选择一个包含一些非英语文本的表格和列,然后做SELECT
SELECT col, HEX(col) FROM tbl WHERE ...
正确存储的 UTF-8 的十六进制将是
- 对于空白区域(任何语言):
20
- 英语:、、或
4x
5x
6x
7x
- 对于西欧的大部分地区,重音字母应该是
Cxyy
- 西里尔文、希伯来文和波斯语/阿拉伯语:
Dxyy
- 亚洲大部分地区:
Exyyzz
- 表情符号和一些中文:
F0yyzzww
- 更多详情
所见问题的具体原因和解决方法
截断文本 ( for):Se
Señor
- 要存储的字节未编码为 utf8mb4。解决此问题。
- 此外,请检查读取期间的连接是否为 UTF-8。
带问号的黑钻 ( for );
存在以下情况之一:Se�or
Señor
案例 1(原始字节不是 UTF-8):
- 要存储的字节未编码为 utf8。解决此问题。
- 和 的连接(或)不是 utf8/utf8mb4。解决此问题。
SET NAMES
INSERT
SELECT
- 此外,请检查数据库中的列是否为 (或 utf8mb4)。
CHARACTER SET utf8
案例 2(原始字节为 UTF-8):
- 的连接(或)不是 utf8/utf8mb4。解决此问题。
SET NAMES
SELECT
- 此外,请检查数据库中的列是否为 (或 utf8mb4)。
CHARACTER SET utf8
仅当浏览器设置为 时才会出现黑菱形。<meta charset=UTF-8>
问号(常规问号,非黑菱形)(用于):Se?or
Señor
- 要存储的字节未编码为 utf8/utf8mb4。解决此问题。
- 数据库中的列不是 (或 utf8mb4)。解决此问题。(使用 .)
CHARACTER SET utf8
SHOW CREATE TABLE
- 此外,请检查读取期间的连接是否为 UTF-8。
Mojibake ( 用于 ):
(此讨论也适用于双重编码,它不一定可见。Señor
Señor
- 要存储的字节需要采用 UTF-8 编码。解决此问题。
- 连接 when 和 text 需要指定 utf8 或 utf8mb4。解决此问题。
INSERTing
SELECTing
- 需要声明该列(或 utf8mb4)。解决此问题。
CHARACTER SET utf8
- 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 种不同修复程序;请仔细挑选
相关新闻: 非法混合排序规则
评论
utf8mb4
collation-server
character-set-server
mysqld
SET NAMES utf8mb4
utf8mb4
utf8mb4_0900_ai_ci
FUNCTION
STORED PROCEDURE
DROP
SET NAMES
CREATE
将代码 IDE 语言设置为 UTF-8
将 <meta charset=“utf-8”>添加到收集数据表单的网页标题中。
检查您的 MySQL 表定义如下所示:
CREATE TABLE your_table ( ... ) ENGINE=InnoDB DEFAULT CHARSET=utf8
如果您使用的是 PDO,请确保
$options = array(PDO::MYSQL_ATTR_INIT_COMMAND=>'SET NAMES utf8'); $dbL = new PDO($pdo, $user, $pass, $options);
如果您已经有一个存在上述问题的大型数据库,您可以尝试使用 SIDU 使用正确的字符集导出,并使用 UTF-8 导入回来。
评论
DEFAULT CHARSET
$db = new PDO('dblib:host=host;dbname=db;charset=UTF8', $user, $pwd);
ALTER DATABASE
CREATE TABLE
根据服务器的设置方式,您必须相应地更改编码。从你所说的 utf8 应该效果最好。但是,如果您遇到奇怪的字符,将网页编码更改为 ANSI 可能会有所帮助。
这在我设置 PHP MySQLi 时帮助了我。这可能有助于您了解更多: Notepad++ 中的 ANSI 到 UTF-8
评论
ANSI
latin1
“
E2809C
latin1
在服务器迁移后,我的两个项目也遇到了类似的问题。在搜索并尝试了很多解决方案之后,我遇到了这个:
mysqli_set_charset($con,"utf8mb4");
将这一行添加到我的配置文件后,一切正常!
我为 MySQLi 找到了这个解决方案——PHP mysqli set_charset() 函数——当我想要解决 HTML 查询中的插入时。
评论
mysqli
PDO
我也在寻找同样的问题。我花了将近一个月的时间才找到合适的解决方案。
首先,您必须将所有最近的 CHARACTER 和 COLLATION 更新数据库为 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")
如果它不起作用,请愉快地寻找正确的解决方案。
评论
SETs
SET
评论