如果您不确定 $encoding 可以设置为哪个值,以下是此扩展支持的所有编码的完整列表
https://php.net/manual/en/mbstring.supported-encodings.php
(PHP 4 >= 4.0.6, PHP 5, PHP 7, PHP 8)
mb_strlen — 获取字符串长度
返回 string string
中字符的数量,字符编码为 encoding
。多字节字符计为 1 个。
如果编码未知,将生成级别为 E_WARNING
的错误。
版本 | 描述 |
---|---|
8.0.0 |
encoding 现在可以为空。 |
如果您不确定 $encoding 可以设置为哪个值,以下是此扩展支持的所有编码的完整列表
https://php.net/manual/en/mbstring.supported-encodings.php
mb_strlen 的速度根据指定的字符集而有很大差异。
如果您需要字符串的字节长度(strlen 由于 mbstring.func_overload 不再可靠),您应该使用 <?php mb_strlen($string, '8bit'); ?>。
这是确定字符串字节长度的最快方法(虽然仍然比 strlen 慢)。其他单字节字符集(ASCII、ISO-8859-1 等)比 8bit 慢几倍。
刚刚对 mbs 函数进行了一些基准测试(使用 lorem ipsum 文本进行 1,000,000 次测试)
特别是 mb_strtolower 和 mb_strtoupper 速度非常慢(比普通函数慢 100 倍)。其他函数也类似,但有时慢 5 倍。
在高频脚本中使用 mb_ 函数时要谨慎。
# 测试运行:1000000
# 对比 strlen 和 mb_strlen
# 普通 strlen:3.6795361042023 ms,平均:3.6795361042023E-6 ms
# mb_strlen:5.5934538841248 ms,平均:5.5934538841248E-6 ms
ok 1 - mb_strlen 比 strlen 慢
# mb_strlen 比 strlen 慢 1.52 倍
#
#
# 对比 strpos 和 mb_strpos
# 普通 strpos:5.5523281097412 ms,平均:5.5523281097412E-6 ms
# mb_strlen:31.180974960327 ms,平均:3.1180974960327E-5 ms
ok 2 - mb_strlen 比 strlen 慢
# mb_strpos 比 strpos 慢 5.62 倍
#
#
# 对比 substr 和 mb_substr
# 普通 substr:3.4437320232391 ms,平均:3.4437320232391E-6 ms
# mb_strlen:3.5374181270599 ms,平均:3.5374181270599E-6 ms
ok 3 - mb_strlen 比 strlen 慢
# mb_substr 比 substr 慢 1.03 倍
#
#
# 对比 strtolower 和 mb_strtolower
# 普通 strtolower:4.446839094162 ms,平均:4.446839094162E-6 ms
# mb_strlen:193.44901108742 ms,平均:0.00019344901108742 ms
ok 4 - mb_strlen 比 strlen 慢
# mb_strtolower 比 strtolower 慢 43.5 倍
#
#
# 对比 strtoupper 和 mb_strtoupper
# 普通 strtoupper:3.0210740566254 ms,平均:3.0210740566254E-6 ms
# mb_strlen:340.71775603294 ms,平均:0.00034071775603294 ms
ok 5 - mb_strlen 比 strlen 慢
# mb_strtoupper 比 strtoupper 慢 112.78 倍
如果您发现自己没有 mb 字符串函数,并且无法轻松更改,那么对于 utf8 字符,mb_strlen 的一个快速替代方案是使用一个启用 utf8 的 PCRE 正则表达式。
$strlen = preg_match_all("/.{1}/us",$utf8string,$dummy);
这基本上是一个丑陋的 hack,它计算所有单个字符匹配,并且我预计它在大型字符串上会非常慢。
可能不清楚 PHP 是否实际支持 utf-8,这是当前 Web 文档的事实上的标准字符编码,它支持大多数人类语言。好消息是:它确实支持。
我编写了一个测试程序,它成功地读取了一个 utf-8 文件(没有 BOM),并使用 mb_substr、mb_strlen 和 mb_strpos 操作字符(mb_substr 通常应该避免使用,因为它必须始终从字符位置 0 开始搜索)。
使用各种 utf-8 编码的 Unicode 测试字符(长度最大为 4 个字节)的结果大多是正确的,只是重音符号总是错误地被视为单独的字符,而不是与前一个字符组合在一起;这个问题可以通过编程在必要时解决。
感谢 Peter Albertsson 的演示!
在花费了 8 个多小时跟踪我 mbstring-func_overloaded 环境中的两个特定错误之后,我学到了一条非常重要的经验
许多开发人员依赖 strlen 来提供字符串中的字节数。虽然 mb-overloading 有很多优势,但最难发现的陷阱就是这个问题。
两个示例(来自之前发现的两个错误)
1. 将字符串写入文件
<?php
$str = "string with utf-8 chars åèä - doo-bee doo-bee dooh";
$fp = fopen($this->_file, "wb");
if ($fp) {
$len = strlen($str);
fwrite($fp, $str, $len);
}
?>
PS 这是在 PEAR::Cache_Lite 包(Lite.php)中发现的 - 已报告
2. 遍历字符串的字符
<?php
$str = "string with utf-8 chars åèö - doo-bee doo-bee dooh";
$newStr = "";
for ($i = 0; $i < strlen($str); $i++) {
$newStr .= $str[$i];
}
?>
这两种情况都将无法保存/存储 $str 中的最后几个字符。这可能很难发现,对于序列化字符串、xml 等尤其致命。
因此,尝试避免这些情况以支持过载环境,并且如果在这样的环境下发现问题,请记住 Peter Albertssons 的建议。
我最近一直在处理一些有趣的 html 字符,由于在 mysql 和 php 之间操作它们时遇到了噩梦,我将数据库列设置为 utf8,然后使用 html 实体 "ọ" 将字符存储为 ọ 在数据库中,并将 php 的编码设置为 "utf8"。
这就是 mb_strlen 比 strlen 更实用的地方。虽然 strlen('ọ') 的结果为 3,但 mb_strlen('ọ','UTF-8') 的结果为 1,符合预期。
但 mysql 中的 left(column1,1) 仍然对多字节字符串给出错误的字符。在上面的示例中,我不得不使用 left(column1,3) 从 mysql 获取正确的字符串。我现在正准备研究 mysql 中的多字节操作。