PHP卷曲引用字符编码问题

时间:2014-02-12 01:39:59

标签: php mysql encoding utf-8

我知道在不同的字符集之间存在一个古老的字符编码问题,但是我被困在一个与Window的“曲线引号”相关的问题上。

我们有一个客户喜欢将数据复制并粘贴到文本字段中,然后将其发布到我们的应用上。该数据通常会包含卷曲引号。我曾经使用以下方法将它们转换为正常的对应物:

function convert_smart_quotes($string)  { 

$badwordchars=array("\xe2\x80\x98", "\xe2\x80\x99", "\xe2\x80\x9c", "\xe2\x80\x9d", "\xe2\x80\x93", "\xe2\x80\x94", "\xe2\x80\xa6");

$fixedwordchars=array("'", "'", '"', '"', '-', '--', '...');

return str_replace($badwordchars,$fixedwordchars,$string); 

}

这个工作好几个月了。然后经过一些更改(我们切换服务器,对系统进行更新,升级PHP等等),我们知道它不再起作用了。所以,我看看,我了解到“卷曲引号”都变成了不同的字符。在这种情况下,他们将变成以下内容:

“=¡È

“=¡É

'=¡Æ

'=¡Ç

这些字符在保存在数据库中时会显示为被诅咒的“黑钻石问号符号”。 mySQL数据库位于latin1_swedish_ci中,接收消息的应用程序也是如此。所以,虽然我知道utf-8更好,但它必须保留在latin1_swedish_ci或ISO-8859-1中,否则我们将不得不重建所有内容......这是不可能的。

我的网页和表单均以utf-8发布。如果我将其更改为ISO-8859-1,则引号会成为问号。

我已经尝试在字符串中搜索“¡È”或“¡É”的出现并用正常引号替换它们,但我无法让它工作。我通过在上面的函数中添加以下内容来实现它:

$string = str_replace("xa1\xc8", '"', $string);
$string = str_replace("xa1\xc9", '"', $string);
$string = str_replace("xa1\xc6", "'", $string);
$string = str_replace("xa1\xc7", "'", $string);

我已经被困在这几个小时了,并且无法在网上找到任何真正的帮助。你可以想象,googleing“¡É”并没有带来非常具体的反应。

感谢任何指导!

2 个答案:

答案 0 :(得分:8)

您的问题是您接受用户的UTF-8输入,然后将其插入数据库,就像它是Latin1(ISO-8859-1)一样。 (请注意,latin1_swedish_ci不是编码,而是整理(对于Latin1)。请参阅this SO question on the difference。以解决您的角色编码问题,整理并不重要。)

您应该使用强大的方法将UTF-8字符串转换为Latin1,例如iconv,而不是手动识别重要的UTF-8序列并替换它们。

请注意,这是有损转换:Latin1中不存在某些UTF-8字符(如引号)。你可以选择忽略这些字符(用空字符串替换它们,或者用其他东西替换它们),或者你可以选择音译它们(用等效的替代它们替换它们) ,就像"的卷曲引语一样......但如果有人在表单中放置,你会怎么做?

iconv会尝试在可能的位置进行音译:

// convert from utf8 to latin1, approximating out of range characters
// by the closest latin1 alternative where possible (//TRANSLIT)
$latinString = iconv("UTF-8", "ISO-8859-1//TRANSLIT", $utf8String);

(您也可以将其配置为忽略所有超出范围的字符 - 有关详细信息,请参阅iconv's documentation。)

如果您不想添加新库,PHP还附带utf_decode函数:

$latinString = utf_decode($utf8String);

然而,PHP的设计并没有考虑多个字符编码,因此我更倾向于远离处理编码的(有时是错误的)标准库函数。

您还应该考虑阅读 The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

答案 1 :(得分:3)

您可以使用以下代码来解决此问题。

$str = mb_convert_encoding($str, 'HTML-ENTITIES', 'UTF-8');

$str = mb_convert_encoding($str, 'HTML-ENTITIES', 'auto');

可以在php文档网站上找到更多信息。

相关问题