strlen()和 UTF-8 编码

回答 6 浏览 3.4万 2012-06-14

假设采用UTF-8编码,在PHP中采用strlen(),那么这个字符串的长度是否有可能是4?

我只想知道strlen()的情况,而不是其他的函数

这是一个字串。

$1�2

我在自己的电脑上测试了一下,我验证了UTF-8编码,得到的答案是6。

我在strlen的手册中没有看到任何东西,也没有看到我读过的关于UTF-8的任何东西,可以解释为什么上面的一些字符会被算作小于1。

PS:这个问题和答案(4)来自于我在Ebay上购买的ZCE模拟测试。

Jon Lyles 提问于2012-06-14
strlen是计算字节数,而不是计算字符数Esailija 2012-06-14
UTF-8 字符是多字节字符,在使用strlen 时,它们的长度与字节数一样多。使用 php.net/manual/en/function.mb-strlen.php 获得预期结果。Rem.co 2012-06-14
@RemcoOverdijk utf-8编码的字符可以是1-6个字节的长度。Esailija 2012-06-14
@Esailija 不对,UTF-8字符(编码的代码点)最多可以有4个字节的长度。Pavel Radzivilovsky 2012-06-15
@PavelRadzivilovsky 谢谢你的更正。Esailija 2012-06-15
6 个回答
#1楼
得票数 21

如何使用mb_strlen()?

http://lt.php.net/manual/en/function.mb-strlen.php

但是如果你需要使用 strlen,你可以通过设置 mbstring.func_overload 指令来配置你的 webserver,这样它就会在你的脚本中自动将 strlen 的使用替换为 mb_strlen。

Anton 提问于2012-06-14
Anton 修改于2012-06-14
是的,我在其他答案中看到了mb_strlen(),但我特别关注的是strlen()。Jon Lyles 2012-06-14
为了回答你的评论问题,我修改了我的答案。Anton 2012-06-14
ew,我不知道mbstrung.func_overload - 启用它将破坏我的一堆代码,因为我总是认为strlen是以字节为单位的长度。thomasrutter 2018-10-19
#2楼 已采纳
得票数 14

你发布的字符串有六个字符:$1�2(美元符号,数字一,小写i带重音,倒置的问号,二分之一的分数,数字二)。

如果用该字符串的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美元)。

bames53 提问于2012-06-14
bames53 修改于2014-09-23
#3楼
得票数 10

需要使用多字节字符串函数mb_strlen(),如。

mb_strlen($string, 'UTF-8');
Haim Evgi 提问于2012-06-14
#4楼
得票数 5

很可能在准备问题和你阅读问题之间的某个时间点上,有些过程将其中的非ASCII字符弄乱了,所以问题原本是关于某个含有4个字符的字符串的。

序列�是在编码替换字符U时得到的UTF-8 格式的 +FFFD (�) 并以 latin1 格式解释结果。例如,在从文件中读取文本时,此字符可替代不编码任何字符的字节序列。发生的事情很可能是这样的:

最初的问题,存储在一个latin1文本文件中,有。$1¢2 (你可以用任何非ASCII字符替换¢)

该文件被一个使用UTF-8的程序读取。由于对应于"¢"的字节不能被解释,该程序将其替换,并读取了文本$1�2。然后这个文本被用UTF-8写出来,结果在文件中出现了$1\xEF\xBF\xBD2

然后有第三个程序来读取拉丁文1的文件,并显示$1�2.

Joni 提问于2012-06-14
#5楼
得票数 2

不。

我将使用一个矛盾证明法。

strlen计算字节数,所以strlen为4时,该字符串中需要有精确的4个字节

UTF8编码需要每个字符至少有1个字节

我们已经确定了这一点。

  1. 有4个字节的
  2. 一个字符由不少于1个字节来代表

...然而,我们有6个字符....,这是一个矛盾。所以,没有。

然而,不完全清楚的是,显示软件(例如,网络浏览器)使用哪种字符集来解释该字符串。它可能使用了一些不常见的编码方案,其中一个字符可以用少于8位来表示。如果是这种情况,那么4个字节可以显示为6个字符。因此,字符串可能是utf8,但浏览器可能决定将其解释为,例如,一些5位字符集。

goat 提问于2012-06-14
#6楼
得票数 1

许多UTF-8字符需要几个字节而不是一个字节。这就是UTF-8的构造(这就是为什么你可以在一个集合中拥有这么多字符)。

试试 mb_strlen() 代替。

Madara's Ghost 提问于2012-06-14
有趣的事实:在理论上,utf-8每个字符最多可以使用8个字节,尽管这个长度到现在还没有被使用--使用的最大长度是一堆4字节的字符(例如,像Clef-sign和一些中文字符)。oezi 2012-06-14
strlen()怎么样,答案有可能小于6吗?Jon Lyles 2012-06-14
@JonLyles:strlen()计算字符串中的字节数。如果字符串有6个字节,它的结果是6。Madara's Ghost 2012-06-14
@Truth.谢谢,它已经修好了。Jon Lyles 2012-06-14