我只关心 strlen() 函数,不关心其他函数。
以下是该字符串: $1�2
我已经在自己的电脑上测试过,并验证了 UTF-8 编码,得到的答案是 6。
我在 strlen 的手册中没有看到任何关于为什么某些字符计算值小于一的解释,也没有在有关 UTF-8 的文献中找到相关信息。
PS: 这个问题和答案 (4) 来自我在 Ebay 上购买的 ZCE 模拟考试。
使用 mb_strlen() 呢?
http://lt.php.net/manual/en/function.mb-strlen.php
但如果你需要使用 strlen,可以通过设置 mbstring.func_overload 指令为 2 来配置你的 Web 服务器,这样它将自动替换你脚本中使用 strlen 为 mb_strlen。
mbstrung.func_overload
- 启用它会破坏我的一堆代码,因为我总是假设 strlen 是以字节为单位的长度。 - thomasrutter你发布的字符串长度为6个字符:$1�2(美元符号、数字1、带分音符的小写i、倒置问号、一半分数、数字2)
如果使用该字符串的UTF-8表示形式调用strlen()函数,则会得到一个长度为9的结果(虽然有多种不同长度的表示形式)。
然而,如果我们将该字符串存储为ISO 8859-1或CP1252,则会得到一个6字节长的序列,该序列作为UTF-8是合法的。将这6个字节重新解释为UTF-8会导致4个字符:$1�2(美元符号、数字1、Unicode替换字符、数字2)。也就是说,单个字符“�”的UTF-8编码与三个字符“�”的ISO-8859-1编码完全相同。
当UTF-8解码器读取的数据不是有效的UTF-8数据时,替换字符经常被插入。
看起来原始字符串经历了多重误解层面;通过对非UTF-8数据使用UTF-8解码器(生成$1�2),以及通过你用于分析该数据的任何工具(生成$1�2)。
很可能在问题准备和你阅读问题之间的某个过程中,一些非ASCII字符被破坏了,因此该问题最初是关于一个包含4个字符的字符串的。
当你将替换字符U+FFFD(�)用UTF-8编码,并以latin1解释结果时,会得到序列�
。例如,在从文件中读取文本时,如果字节序列没有编码任何字符,则使用该字符来替换这些序列。发生的情况很可能是这样的:
原始问题存储在一个latin1文本文件中,其中包括:$1¢2
(可以用任何非ASCII字符代替¢)
该文件被一个使用UTF-8的程序读取。由于无法解释对应于¢的字节,程序会替换它并读取文本$1�2
。 然后,该文本使用UTF-8写出,导致在文件中出现$1\xEF\xBF\xBD2
。
然后,某些第三方程序以latin1格式读取该文件,并显示$1�2
。
不行。
我将采用反证法。
strlen计算的是字节数,因此,字符串中必须恰好有4个字节。
UTF8编码需要每个字符至少1个字节。
我们已经确定:
......然而,我们有6个字符......这是一个矛盾。所以,不行。
但是,仍不完全清楚的是,显示软件(例如,Web浏览器)使用哪种字符集来解释该字符串。它可能使用某些不常见的编码方案,其中一个字符可以由少于8位表示。如果是这种情况,则4个字节可以显示为6个字符。因此,字符串可以是utf8,但浏览器可以决定将其解释为某个5位字符集。
mb_strlen()
代替。strlen()
函数计算字符串中的字节数。如果该字符串有6个字节,则结果为6。 - Madara's Ghost
strlen
函数计算的是字节数而不是字符数。 - Esailijastrlen
函数时,它们的长度以字节为单位计算。请使用http://php.net/manual/en/function.mb-strlen.php获取预期结果。 - Rem.co