UTF8编码问题 - 有很好的例子

Liz*_*ard 23 php mysql utf-8 character-encoding

我有以下字符编码问题,不知何故我设法将不同字符编码的数据保存到我的数据库(UTF8)下面的代码和输出显示2个示例字符串以及它们如何输出.其中1个需要更改为UTF8而另一个已经是.

我该如何/应该检查是否应该对字符串进行编码?例如,我需要正确输出每个字符串,那么如何检查它是否已经是utf8或是否需要转换?

我使用PHP 5.2,mysql myisam表:

CREATE TABLE IF NOT EXISTS `entities` (
  ....
  `title` varchar(255) NOT NULL
  ....
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

<?php
$text = $entity['Entity']['title'];
echo 'Original : ', $text."<br />";
echo 'UTF8 Encode : ', utf8_encode($text)."<br />";
echo 'UTF8 Decode : ', utf8_decode($text)."<br />";
echo 'TRANSLIT : ', iconv("ISO-8859-1", "UTF-8//TRANSLIT", $text)."<br />";
echo 'IGNORE TRANSLIT : ', iconv("ISO-8859-1", "UTF-8//IGNORE//TRANSLIT", $text)."<br />";
echo 'IGNORE   : ', iconv("ISO-8859-1", "UTF-8//IGNORE", $text)."<br />";
echo 'Plain    : ', iconv("ISO-8859-1", "UTF-8", $text)."<br />";
?>
Run Code Online (Sandbox Code Playgroud)

输出1:

Original : France Télécom
UTF8 Encode : France Télécom
UTF8 Decode : France T?l?com
TRANSLIT : France Télécom
IGNORE TRANSLIT : France Télécom
IGNORE : France Télécom
Plain : France Télécom
Run Code Online (Sandbox Code Playgroud)

输出2: ###

Original : Cond? Nast Publications
UTF8 Encode : Condé Nast Publications
UTF8 Decode : Cond?ast Publications
TRANSLIT : Condé Nast Publications
IGNORE TRANSLIT : Condé Nast Publications
IGNORE : Condé Nast Publications
Plain : Condé Nast Publications
Run Code Online (Sandbox Code Playgroud)

谢谢你在这个时间.字符编码,我不能很好!

更新:

echo strlen($string)."|".strlen(utf8_encode($string))."|";
echo (strlen($string)!==strlen(utf8_encode($string))) ? $string : utf8_encode($string);
echo "<br />";
echo strlen($string)."|".strlen(utf8_decode($string))."|";
echo (strlen($string)!==strlen(utf8_decode($string))) ? $string : utf8_decode($string);
echo "<br />";

23|24|Cond? Nast Publications
23|21|Cond? Nast Publications

16|20|France Télécom
16|14|France Télécom
Run Code Online (Sandbox Code Playgroud)

Pek*_*ica 28

这可能是该mb_detect_encoding()功能的工作.

在我使用它的有限经验中,当用作通用的"编码嗅探器"时,它不是100%可靠 - 它检查某些字符和字节值的存在以进行有根据的猜测 - 但在这种狭窄的情况下(它需要区分UTF-8和ISO-8859-1)它应该工作.

<?php
$text = $entity['Entity']['title'];

echo 'Original : ', $text."<br />";
$enc = mb_detect_encoding($text, "UTF-8,ISO-8859-1");

echo 'Detected encoding '.$enc."<br />";

echo 'Fixed result: '.iconv($enc, "UTF-8", $text)."<br />";

?>
Run Code Online (Sandbox Code Playgroud)

对于不包含特殊字符的字符串,您可能会得到不正确的结果,但这不是问题.

  • 根据我的经验,encoding_list的顺序很重要.**"UTF-8,ISO-8859-1"**将提供除**"ISO-8859-1,UTF-8"**之外的其他结果** (5认同)

Seb*_*oli 9

我做了一个解决所有这些问题的功能.它叫做Encoding :: toUTF8().

<?php
$text = $entity['Entity']['title'];
echo 'Original : ', $text."<br />";
echo 'Encoding::toUTF8 : ', Encoding::toUTF8($text)."<br />";
?>
Run Code Online (Sandbox Code Playgroud)

输出:

Original : France Télécom
Encoding::toUTF8 : France Télécom

Original : Cond? Nast Publications
Encoding::toUTF8 : Condé Nast Publications
Run Code Online (Sandbox Code Playgroud)

只要您知道它是在Latin1(iso 8859-1),Windows-1252或UTF8上,您就不需要知道字符串的编码是什么.字符串也可以混合使用它们.

Encoding :: toUTF8()会将所有内容转换为UTF8.

我这样做是因为一项服务给了我一个混乱的数据,将UTF8和Latin1混合在同一个字符串中.

用法:

$utf8_string = Encoding::toUTF8($utf8_or_latin1_or_mixed_string);

$latin1_string = Encoding::toLatin1($utf8_or_latin1_or_mixed_string);
Run Code Online (Sandbox Code Playgroud)

下载:

http://dl.dropbox.com/u/186012/PHP/forceUTF8.zip

我已经包含了另一个函数Encoding :: fixUFT8(),它将修复每个看起来乱码的UTF8字符串.

用法:

$utf8_string = Encoding::fixUTF8($garbled_utf8_string);
Run Code Online (Sandbox Code Playgroud)

例子:

echo Encoding::fixUTF8("Fédération Camerounaise de Football");
echo Encoding::fixUTF8("Fédération Camerounaise de Football");
echo Encoding::fixUTF8("FÃÂédÃÂération Camerounaise de Football");
echo Encoding::fixUTF8("Fédération Camerounaise de Football");
Run Code Online (Sandbox Code Playgroud)

将输出:

Fédération Camerounaise de Football
Fédération Camerounaise de Football
Fédération Camerounaise de Football
Fédération Camerounaise de Football
Run Code Online (Sandbox Code Playgroud)


Dr.*_*lle 6

另一种方式,可能更快,更不可靠:

echo (strlen($str)!==strlen(utf8_decode($str)))
  ? $str                //is multibyte, leave as is
  : utf8_encode($str);  //encode
Run Code Online (Sandbox Code Playgroud)

它比较原始字符串的长度和utf8_decoded字符串.包含多字节字符的字符串,其strlen与类似的单字节编码的strlen不同.

例如:

strlen('Télécom') 
Run Code Online (Sandbox Code Playgroud)

应该在Latin1中返回7,在UTF8中返回9