PHP:从ISO-8859-1转换“’”字符为UTF-8时出现问题

5

我在使用PHP将ISO-8859-1编码的数据库内容转换为UTF-8时遇到了一些问题。我运行以下代码进行测试:

// Connect to a latin1 charset database 
// and retrieve "Georgia O’Keeffe", which contains a "’" character
$connection = mysql_connect('*****', '*****', '*****');
mysql_select_db('*****', $connection);
mysql_set_charset('latin1', $connection);
$result = mysql_query('SELECT notes FROM categories WHERE id = 16', $connection);
$latin1Str = mysql_result($result, 0);
$latin1Str = substr($latin1Str, strpos($latin1Str, 'Georgia'), 16);

// Try to convert it to UTF-8
$utf8Str = iconv('ISO-8859-1', 'UTF-8', $latin1Str);

// Output both
var_dump($latin1Str);
var_dump($utf8Str);

当我在Firefox的源视图中运行此代码时,确保Firefox的编码设置为“Western (ISO-8859-1)”,我会得到以下结果:

asd

到目前为止,一切都很好。第一个输出包含了那个奇怪的引号,因为它是在ISO-8859-1中,所以在Firefox中可以正确显示。
当我将Firefox的编码设置更改为“UTF-8”后,结果如下:

asd

引号去哪了?难道iconv()不应该将其转换为UTF-8吗?
2个回答

16

U+2019 RIGHT SINGLE QUOTATION MARK 不是 ISO-8859-1 字符集中的字符。它作为 0x92 是一个 windows-1252 字符。而实际的 ISO-8859-1 字符 0x92 是一个名为 "Private Use 2" 的极少使用的C1控制字符

将 Windows-1252 文本数据错误标记为字符集 ISO-8859-1 是非常常见的。许多网络浏览器和电子邮件客户端在处理 MIME 字符集 ISO-8859-1 时会将其视为 Windows-1252 字符以适应此类标记错误,但这不是标准行为。因此,在标记为 ISO-8859-1 的内容中应注意避免生成这些字符。

看起来这就是所发生的事情。请将“ISO-8859-1”更改为“windows-1252”。


哇,我做到了,我在UTF-8模式下看到了U+2019!但是使用"windows-1252"将大量数据从"ISO-8859-1"转换为"UTF-8"是否安全?换句话说,所有的ISO-8859-1字符是否仍然能够正确转换? - mattalxndr
1
字符0x80-0x9F将无法正确转换。但这些是几乎从不使用的控制字符。 - dan04
1
如果您检查字符串中的字符范围并发现任何字符,则很有可能该字符串是使用Windows-1252编码的。如果您没有在该范围内找到任何字符,则更可能是ISO-8859-1编码。 - user212218
1
如果我能给你+10分,我一定会的。这个问题让我困扰了好几周,而你的答案解决了其他建议无法解决的难题。 - AdRock

0
这将解决你的问题,假设你的页面头部的字符集是 utf-8:
// Opens a connection to a MySQL server
$connection = mysql_connect ($server, $username, $password);
$charset = mysql_client_encoding($connection);
$flagChange = mysql_set_charset('utf8', $connection);
echo "The character set is: $charset</br>mysql_set_charset result:$flagChange</br>";

如果更新为 mysqli,这个还能正常工作吗? - John

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