使用utf8还是不使用utf8——MySQL和PHP字符编码问题

4
我在MySQL中存储了一个字符串,它看起来像这样:یکی از Ø,我的表的字符集是utf8,排序规则是utf8_general_ci
当我从MySQL检索该字符串时,浏览器会显示它,如下所示:یکی از بهترین راه 并且没问题(它是波斯语)。
注意:
- 我在连接MySQL后使用了 mysql_query("SET NAMES 'utf8_persian_ci'");。 - 我在每个页面的标签中加入了<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />标签。
现在,我需要使用mysql_query("SET NAMES 'utf8'");
但是使用后,浏览器显示该字符串如下所示:یکی از Ø(与存储在MySQL中相同)。
我该如何更改我的MySQL存储记录并解决我的问题?或者使用一些PHP代码来转换输出编码?

我没有测试过,但是 utf8_encode() 可能会对你有所帮助。 - romainberger
1
@romainberger - ISO-8859-1与此有什么关系? - Álvaro González
@romainberger:我使用了您的建议,将从MySQL检索到的字符串转换后传递给HTML。但是它显示另一种奇怪的文本。 - masoud
请检查您查询所涉及的数据库、表和列的排序规则。为了获得最佳结果,它必须是utf8_persian_ci。 - Alexander Taver
请注意mysql_query()函数已被弃用(包括其他mysql_xx()函数)。它已经过时且不安全,请考虑切换到mysqli_xxx()函数或PDO库。另请参见https://dev59.com/3Gcs5IYBdhLWcg3wcDaZ。 - SDC
3个回答

4
你的问题在于SET NAMES 'utf8_persian_ci'命令是无效的( utf8_persian_ci 是一个排序规则,而不是编码格式)。如果你在终端中运行它,你会看到一个错误信息Unknown character set: 'utf8_persian_ci'。因此,当应用程序存储数据时,它使用了latin1字符集。MySQL将您的输入解释为 latin1 字符,然后编码为UTF-8进行存储。同样,当数据被取出时,MySQL会将其从UTF-8转换回 latin1,并(希望大部分时间)还原成您提供的原始字节。
换句话说,你数据库中的所有数据都被完全搞砸了,但是它确实能够工作。
要解决这个问题,您需要撤销所做的更改。最简单的方法是使用PHP:
  1. SET NAMES latin1;
  2. 从每个表中选择每个文本字段。
  3. SET NAMES utf8;
  4. 使用相同的未更改字符串更新相同的行。
或者你可以在MySQL内执行这些步骤,但是这很棘手,因为MySQL理解数据属于某种字符集。您需要将文本列修改为BLOB类型,然后使用utf8字符集将其转换回文本类型。请参见MySQL文档中标记为“警告”的底部部分
在执行任何PHP数据库访问时,请确保始终使用mysql_set_charset('utf8')!否则,您会再次搞砸事情。(注意,不要使用简单的mysql_query('SET NAMES utf8') !有一些特殊情况(例如重置连接),这可能会在您不知情的情况下重置为latin1 mysql_set_charset()将在必要时设置字符集。)
最好是放弃mysql_*函数并改用PDO,在您的PDO dsn中带有charset=utf8参数。

我链接的MySQL文档详细介绍了这一点。基本上,ALTER TABLE mytable MODIFY mycolumn BLOB 然后 ALTER TABLE mytable MODIFY mycolumn [original-type] CHARACTER SET utf8 - Francis Avila

1

你可能需要更改列的字符集和排序规则。

尝试执行以下查询:

ALTER TABLE  `YOUR_TABLE_NAME` CHANGE  `YOUR_COLUMN_NAME`  `YOUR_COLUMN_NAME` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL

(在这个例子中,我假设VARCHAR具有默认的NULL值)
如果这对您有用,那么您可以在my.conf文件中插入以下代码,使utf8成为默认字符集:
default-character-set   = utf8

我的表字符集和排序规则目前是 utf8utf8_general_ci。你的意思是我应该重新转换它们吗? - masoud
你是用这个字符集还是其他字符集插入数据的?我在Java中遇到过这种问题,不得不重新使用相同的字符集在涉及通信的所有部分(即客户端、服务器和MySQL)中重新插入所有数据。 - Alepac

1
可能的解决方案:
  1. 将 "AddDefaultCharset UTF-8" 添加到您网站的 .htaccess 文件中。
  2. 在您的 PHP 文件顶部添加 header('Content-Type: text/html; charset=utf-8') 。
  3. 对需要以波斯语显示的数据使用 utf8_encode() php 函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接