2020-09-27 更新

在代码中使用 mb_strlen($str)mb_substr($str, 1) 隐藏用户名,服务器端(php 5.2)执行出现了乱码。针对服务端 php 脚本文件做了以下补充测试:

服务器环境:windows server 2008 R2 Enterprise,64x,php5.2.17,php 脚本,文件编码 utf-8。

echo strlen('中国'),'<br/>';
echo mb_strlen('中国'),'<br/>';
echo mb_strlen('中国','utf-8'),'<br/>';
echo mb_strlen('中国','gb2312'),'<br/>';
echo mb_strlen('中国','gbk'),'<br/>';
#输出结果
6
6
2
4
3

本地环境:win7,64x,php7.3.2,php 脚本,文件编码 utf-8。

echo strlen('中国'),'<br/>';
echo mb_strlen('中国'),'<br/>';
echo mb_strlen('中国','utf-8'),'<br/>';
echo mb_strlen('中国','gb2312'),'<br/>';
echo mb_strlen('中国','gbk'),'<br/>';
#输出结果
6
2
2
4
3

所以,php 低版本(5.2)需要确保本文件编码和函数参数都为 utf-8,这样结果是可信的。高版本结果本身就是可信的,不需要额外配置参数。

#php 低版本 mb_* 函数样例
mb_strlen($str, 'utf-8');
mb_substr($str, 1, $len-1, 'utf-8');

相同点(联系)

strlen()mb_strlen() 都是属于判断字符串长度的函数。从名称上也可以看出来,后者是对前者扩展。

区别

strlen() 对于英文字符计算正确,但对于中文字符,如:“中国”,结果变成了 6,即一个中文字符占用 3 个长度。猜测函数内部根据表示字符编码的字节数来计算长度的。对于纯中文情况下,可以通过结果除以 3 来修正预期的结果,但如果是中英文混合,或者还参杂其他类型的语言的字符串,就很难去计算预期长度了。

mb_strlen() 在计算时,若选定内码为 UTF8,则会将一个 UTF8 编码的中文字符当作长度 1 来计算,所以长度满足预期。

strlen() 为核心函数,可以直接调用,而 mb_strlen() 为扩展功能函数,需要在 php.ini 取消对 extension=php_mbstring.dll 的注释,引入 mbstring 扩展模块后才能使用。php -m 查看当前已加载的模块。

mb_strlen() 执行速度要比 strlen() 慢好几倍。

mb_strlen 扩展

适用范围 (PHP 4 >= 4.0.6, PHP 5, PHP 7)

mb_strlen() 函数的第一个参数为目标字符串,第二个参数为字符编码。如果省略,则使用内部字符编码,默认为 UTF8。附:如何查看内部字符编码

附:mbstring 扩展中支持的所有字符编码

mb_strlen() 测试

php -r "echo mb_strlen('中国');"

本地环境: win7,64x,php7.3.2,git-bash,内部字符为 zh_CN.UTF-8

$ php -r "echo strlen('中国');"
6
$ php -r "echo mb_strlen('中国');"
2
$ php -r "echo mb_strlen('中国','utf-8');"
2
$ php -r "echo mb_strlen('中国','gb2312');"
4
$ php -r "echo mb_strlen('中国','gbk');"
3

本地环境: win7,64x,php7.3.2,cmd,内部字符为 936 中国 - 简体中文(GB2312)。

C:\Users\Administrator>php -r "echo strlen('中国');"
6
C:\Users\Administrator>php -r "echo mb_strlen('中国');"
2
C:\Users\Administrator>php -r "echo mb_strlen('中国','utf-8');"
2
C:\Users\Administrator>php -r "echo mb_strlen('中国','gbk2312');"
4
C:\Users\Administrator>php -r "echo mb_strlen('中国','gbk');"
3

服务器环境:windows server 2008 R2 Enterprise,64x,php5.2.17,git-bash,内部字符为 zh_CN.UTF-8

$ php -r "echo strlen('中国');"
4
$ php -r "echo mb_strlen('中国');"
4
$ php -r "echo mb_strlen('中国','utf-8');"
3
$ php -r "echo mb_strlen('中国','gb2312');"
2
$ php -r "echo mb_strlen('中国','gbk');"
2

服务器环境:windows server 2008 R2 Enterprise,64x,php5.2.17,cmd,内部字符为 936 中国 - 简体中文(GB2312)。

C:\Users\Administrator>php -r "echo strlen('中国');"
4
C:\Users\Administrator>php -r "echo mb_strlen('中国');"
4
C:\Users\Administrator>php -r "echo mb_strlen('中国','utf-8');"
3
C:\Users\Administrator>php -r "echo mb_strlen('中国','gb2312');"
2
C:\Users\Administrator>php -r "echo mb_strlen('中国','gbk');"
2

初步结论:相同环境下,虽然内部字符(字符编码)不一致,但相同语句输出的结果相同。php7 下默认字符编码就是 utf-8,而php5.2 下不清楚默认编码。php7 下同为中文编码,gb2312 与 gbk 编码的长度不相同。而在 php5.2 下表现一致。

建议使用高版本的 php,且在不确定目标字符串编码类型时,第二参数缺省即可。