关于strlen:php mb_strlen返回值很奇怪

php mb_strlen return value is weird

gb2312是双字节字符集,使用mb_strlen()检查单个汉字将返回2,但是对于另外2个字符,有时结果很奇怪,有人知道为什么吗? 如何获得正确的长度?

1
2
3
4
5
6
7
8
<?php
header('Content-type: text/html;charset=utf-8');//
$a="大";
echo mb_strlen($a,'gb2312'); // output 2
echo mb_strlen($a.$a,'gb2312'); // output 3 , it should be 4
echo mb_strlen($a.'a','gb2312'); // output 2, it should be 3
echo mb_strlen('a'.$a,'gb2312'); // output 3,
?>

谢谢deceze,您的文档非常有帮助,像我这样的人很少了解编码,应该阅读它。每个程序员绝对,绝对需要了解与文本一起使用的编码和字符集


您的字符串可能存储为UTF-8。

"大"的UTF-8代码是E5 A4 A7(根据此网页),因此:

1
2
3
4
5
$a       // 3 bytes, gb2312 -> 2 char (1 + 0.5)
$a . $a  // 6 bytes, gb2312 -> 3 char
$a . 'a' // 4 bytes, gb2312 -> 2 char
'a' . $a // 4 bytes, first byte is <128 so will be interpreted as one
         // single character, gb2312 -> 3 char

这只是一个猜测,但如果以这种方式思考,对我来说完全有意义。您可能可以参考此维基百科页面。

如果您确实要测试,建议您创建一个以gb2312编码保存的单独文件,并使用fopen或其他方式读取它。然后,您将确保它采用所需的编码。


尝试将MB内部编码设置为UTF-8

1
2
/* Set internal character encoding to UTF-8 */
mb_internal_encoding("UTF-8");

http://www.php.net/manual/zh/function.mb-internal-encoding.php


通过将$a ="大";写入PHP文件,变量$a包含源代码文件中引号之间的字节序列。如果该源代码文件保存在UTF-8中,则该字符串是表示字符"大"的UTF-8字节序列。如果源代码文件保存在GB2312中,则它是GB2312字节序列,表示"大"。但是,保存在GB2312中的PHP文件实际上不会解析为有效的PHP,因为PHP需要与ASCII兼容的编码。

mb_strlen应该以给定的编码为您提供给定字符串中的字符数。即mb_strlen('大', 'gb2312')期望该字符串是GB2312字节序列表示形式,并应返回1。即使GB2312是双字节编码,也期望它返回2是错误的。 mb_strlen返回字符数。

strlen('大')将为您提供字节数,因为它是一个简单的老式函数,对编码一无所知,只计算字节数。

底线是:您的期望是错误的,并且"大"的实际编码内容(无论您将源代码保存为什么)与您告诉mb_strlen的编码内容(gb2312 )。因此,mb_strlen无法正确执行其工作,并为您提供各种随机结果。


我认为您必须使用utf-8而不是gb2312

尝试这个:

1
2
3
4
5
6
7
8
<?php
header('Content-type: text/html;charset=utf-8');//
$a="大";
echo mb_strlen($a,'utf8'); // output 1
echo mb_strlen($a.$a,'utf8'); // output 2
echo mb_strlen($a.'a','utf8'); // output 2
echo mb_strlen('a'.$a,'utf8'); // output 2,
?>