php mb_detect_encoding()

时间:2011-11-17 14:01:32

标签: php iso-8859-1 windows-1252

首先,我想说我已经阅读了关于php的mb_detect_encoding的另一篇文章 Strange behaviour of mb_detect_order() in PHP。这肯定再确认我通过追踪和错误学到了什么。但是仍有一些事情让我感到困惑。

我正在构建一个主要是英文网站的html抓取工具,它们收集数据并将其存储为UTF-8 XML。我遇到了一个页面自我声明ISO-8859-1字符集的问题,但它包含Windows-1252独有的字符。特别是正确的单引号(')0x92。据我了解,windows-1252是iso-8859-1的超集,它促使我思考为什么要使用utf8_encode()呢?为什么不使用iconv('Windows-1252','UTF-8',$ str)代替utf8_encode(),因为iso-8859-1中表示的任何内容都会被转换为windows-1252独有的字符(即。€,ƒ''“”)

另外

$ansi = "€";//euro mark, the code file itself is in ansi

$detected = mb_detect_encoding($ansi, "WINDOWS-1252");// $detected == "Windows-1252"
$detected = mb_detect_encoding('a'.$ansi, "WINDOWS-1252");// $detected == FALSE
$detected = mb_detect_encoding($ansi.'a', "WINDOWS-1252");// $detected == "Windows-1252"
$detected = mb_detect_encoding($ansi.'a', "WINDOWS-1252",TRUE);// $detected == FALSE

为什么会这样?如果字符串中的第一个字符不是windows-1252,即使其余部分是,它也会失败?这种行为不会使它变得毫无用处吗?至于区分iso-8859-1和windows-1252

另一件令我困惑的事情是,我想要检测ASCII,ISO-8859-1,windows-1252,UTF-8之间的字符集。是否有可能以一种给我排名最低的方式检测字符串? (即

$ascii = "123"; // desired detect result == 'ASCII'
$iso = "é".$ascii; // desired detect result == 'ISO-8859-1'
$ansi = "€".$iso; // desired detect result == 'Windows-1252'
$utf8 = file_get_contents('utf8.txt', true);//$utf8 == '你好123é€', desired detect result == 'UTF-8'

不应该是我的$ detect_order = array('ASCII','ISO-8859-1','Windows-1252','UTF-8'); 我知道这是不正确的,因为它给了我以下结果

$ascii == 'ASCII'
$iso   == 'ISO-8859-1'
$ansi  == 'ISO-8859-1'
$utf8  == 'ISO-8859-1'

为什么我的检测顺序('ASCII','ISO-8859-1','Windows-1252','UTF-8')错误的我想得到的?

我得到的最接近的期望回报值是

$ascii == 'ASCII'
$iso   == 'ISO-8859-1'
$ansi  == 'ISO-8859-1'
$utf8  == 'UTF-8'

以下两个mb_detect_order数组都给了我上面的值

$detect_order = array('ASCII', 'UTF-8', 'Windows-1252', 'ISO-8859-1');
$detect_order = array('ASCII', 'UTF-8', 'ISO-8859-1', 'Windows-1252');

这让我感到困惑!

p pw,有人可以对此有所了解吗?非常感谢,谢谢!

3 个答案:

答案 0 :(得分:2)

这是known bug

Windows-1251Windows-1252只有在整个过程中才会成功 string由特定范围内的高字节字符组成。这意味着 你将无法获得正确的转换,因为文本将显示为 ISO-8859-1,即使它是Windows-1252

我遇到了从LATIN1转换为UTF-8的问题。我有许多内容从Microsoft Word粘贴并使用MySQL表的VARCHAR字符集存储在LATIN1字段中。你可能知道Word将撇号和引号转换为智能撇号和引号。它们都不会显示在屏幕上,因为这些字符未正确转换。该文本始终标识为ISO-8859-1。要解决此问题,我强制从Windows-1252转换为UTF-8,并且撇号和引号(以及其他字符)都已正确转换。

答案 1 :(得分:1)

不确定我是否会回答您的所有问题,但我们继续:

  

据我所知,windows-1252是iso-8859-1的超集,它促使我思考为什么要使用utf8_encode()呢?为什么不使用iconv(' Windows-1252',' UTF-8',$ str)代替utf8_encode(),因为iso-8859-1中表示的任何内容都会被转换以及windows-1252独有的字符

你不应该为ut8_encode烦恼。转到iconv()或mb_convert_encoding。 ut8_encode仅将ISO-8859-1转换为UTF-8。如果你需要在不同的编码之间进行转换,你应该使用其他功能。

关于欧元马克。不确定是否在某些时候(正式或非正式)添加到ISO-8859-1但下面的声明都返回true

$ansi = "€";//euro mark, the code file itself is in ansi

$detected = mb_detect_encoding($ansi, "WINDOWS-1252", TRUE);// $detected == "Windows-1252"
echo $detected."<br/>-<br/>";
$detected = mb_detect_encoding($ansi, "ISO-8859-1", TRUE);// $detected == ISO-8859-1
echo $detected."<br/>-<br/>";


$detected = mb_detect_encoding($ansi, "WINDOWS-1252");// $detected == "Windows-1252"
echo $detected."<br/>-<br/>";
$detected = mb_detect_encoding($ansi, "ISO-8859-1");// $detected == ISO-8859-1
echo $detected."<br/>-<br/>";

注意,它是严格设置为True或False的结果。这可能解释了为什么

  

不应该是我的$ detect_order =数组(&#39; ASCII&#39;,&#39; ISO-8859-1&#39;,&#39; Windows-1252&#39;,&#39 ; UTF-8&#39);我知道这是不正确的,因为它给了我以下结果

给你ISO-8859-1。我注意到你在后一个顺序中切换了UTF-8,领先于ISO,这就是为什么它最终给你UTF-8的原因。

  

为什么我的检测顺序为(&#39; ASCII&#39;,&#39; ISO-8859-1&#39;,&#39; Windows-1252&#39;&#39; UTF-8& #39;)错误的我想得到什么?

根据php的网站http://us3.php.net/manual/en/function.mb-detect-order.php,在UTF-8之前设置ISO将始终返回ISO。检查他们的无用检测顺序示例。

从我所看到的情况来看,如果你同时拥有ISO-8859-1和Windows-1252,那么你将获得ISO回复。如果你拿出一个或另一个,你将得到两个人留下的任何东西。因此,下面最后2个的定位似乎没有什么区别

  

$ detect_order = array(&#39; ASCII&#39;,&#39; UTF-8&#39;,&#39; Windows-1252&#39;,&#39; ISO-8859-1&#39; );   $ detect_order = array(&#39; ASCII&#39;,&#39; UTF-8&#39;,&#39; ISO-8859-1&#39;,&#39; Windows-1252&#39;);

答案 2 :(得分:-3)

€符号不是utf8编码的一部分!

你必须把它作为€!

或编码到windows-1252或iso-8859-15(与iso-8859-1相同,但有€符号)