在PHP中检测正确的字符编码?

5

我正在尝试检测字符串的字符编码,但是我无法得到正确的结果。
例如:

$str = "€ ‚ ƒ „ …" ;
$str = mb_convert_encoding($str, 'Windows-1252' ,'HTML-ENTITIES') ;
// Now $str should be a Windows-1252-encoded string.
// Let's detect its encoding:
echo mb_detect_encoding($str,'Windows-1252, ISO-8859-1, UTF-8') ;

那段代码输出的是 ISO-8859-1,但应该是 Windows-1252。这有什么问题吗?
编辑:根据 @raina77ow 的回复更新了示例。
$str = "€‚ƒ„…" ; // no white-spaces
$str = mb_convert_encoding($str, 'Windows-1252' ,'HTML-ENTITIES') ;
$str = "Hello $str" ; // let's add some ascii characters
echo mb_detect_encoding($str,'Windows-1252, ISO-8859-1, UTF-8') ;

我又得到了错误的结果。

你正在使用哪个PHP版本?它在这里http://codepad.viper-7.com/NfvdWm上正确显示。顺便说一下,你应该始终首先列出UTF-8,因为它是最受限制的。ISO-8859-1可能根本不需要,因为任何内容都是有效的ISO-8859-1。 - Esailija
@Esailija,你没有使用问题中的任何一个示例代码。尝试使用其中任何一个示例,你将得到结果ISO-8859-1 - GetFree
2个回答

4
在PHP中使用Windows-1252的问题在于,它几乎永远不会被检测到,因为一旦文本包含了0x80至0x9f之外的任何字符,它将无法被检测为Windows-1252编码。 这意味着如果您的字符串只包含普通ASCII字母,如“A”,甚至是空格字符,PHP将会认为它不是有效的Windows-1252,并且会自动切换到下一个可能的编码ISO 8859-1,这是PHP的一个bug,详见https://bugs.php.net/bug.php?id=64667

0

尽管使用ISO-8859-1和CP-1252编码的字符串具有不同的字节代码表示:

<?php
$str = "&euro; &sbquo; &fnof; &bdquo; &hellip;" ;
foreach (array('Windows-1252', 'ISO-8859-1') as $encoding)
{
    $new = mb_convert_encoding($str, $encoding, 'HTML-ENTITIES');
    printf('%15s: %s detected: %10s explicitly: %10s',
        $encoding,
        implode('', array_map(function($x) { return dechex(ord($x)); }, str_split($new))),
        mb_detect_encoding($new),
        mb_detect_encoding($new, array('ISO-8859-1', 'Windows-1252'))
    );
    echo PHP_EOL;
}

结果:

Windows-1252: 802082208320842085 detected:            explicitly: ISO-8859-1
  ISO-8859-1: 3f203f203f203f203f detected:      ASCII explicitly: ISO-8859-1

从这里我们可以看到,mb_detect_encoding 的第二个参数似乎存在问题。使用 mb_detect_order 替代参数会得到非常相似的结果。


示例中的字符不存在于ISO-8859-1中。 - GetFree
我的编码列表中第一个匹配的编码是Windows-1252ISO-8859-1是列表中的第二个编码。 - GetFree
1
@GetFree PHP字符串不是字符,而是字节。任何PHP字符串都是有效的ISO-8859-1,因为任何字节都是有效的ISO-8859-1。 - Esailija
@Esailija,Windows-1252呢?任何字节都是有效的Windows-1252吗?如果是这样的话,那么ISO-8859-1Windows-1252就是一样的了? - GetFree
@GetFree 不,Windows-1252 有5个漏洞。虽然如果目标文本中没有这些漏洞,则对于 mb_detect_encoding 来说,W1252 和 ISO-8859-1 是无法区分的。尽管没有人使用 ISO-8859-1。当他们说他们在使用时,实际上是在使用 Windows-1252。 - Esailija
我不同意。有相当多的人,特别是在Unix世界中,真正使用ISO 8859-1而不是Windows-1252。 - scy

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