【问题标题】:strlen() and UTF-8 encodingstrlen() 和 UTF-8 编码
【发布时间】:2012-06-17 13:01:44
【问题描述】:

假设 UTF-8 编码,以及 PHP 中的 strlen(),这个字符串的长度是否可能是 4?

我只对 strlen() 感兴趣,而不是其他函数

这是字符串:

$1�2

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

我在 strlen 的手册中或我在 UTF-8 上读过的任何内容都没有看到任何可以解释为什么上面的某些字符会小于一个的内容。

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

【问题讨论】:

  • strlen 计算字节数,而不是字符数
  • UTF-8 字符是多字节字符,在使用 strlen 时被视为多字节字符。使用php.net/manual/en/function.mb-strlen.php 获得预期结果。
  • @RemcoOverdijk utf-8 编码字符可以是 1-6 个字节长。
  • @Esailija 不正确,UTF-8 字符(编码代码点)最多可以有 4 个字节长。
  • @PavelRadzivilovsky 感谢指正

标签: php unicode utf-8 strlen


【解决方案1】:

使用 mb_strlen() 怎么样?

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

但如果您需要使用 strlen,可以通过将 mbstring.func_overload 指令设置为 2 来配置您的网络服务器,因此它会自动将您的脚本中使用 strlen 替换为 mb_strlen。

【讨论】:

  • 是的,我在其他答案中看到了 mb_strlen(),但我特别关注 strlen()
  • 修复了我的回答以回答您的评论问题。
  • ew,我不知道 mbstrung.func_overload - 启用它会破坏我的一堆代码,因为我一直认为 strlen 是以字节为单位的长度。
【解决方案2】:

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

如果使用该字符串的 UTF-8 表示调用 strlen(),您将得到 9 的结果(尽管有多种长度不同的表示)。

但是,如果我们将该字符串存储为 ISO 8859-1 或 CP1252,我们将拥有一个六字节长的序列,该序列与 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)。

【讨论】:

    【解决方案3】:

    需要使用多字节字符串函数mb_strlen()like:

    mb_strlen($string, 'UTF-8');
    

    【讨论】:

      【解决方案4】:

      很可能在准备问题和阅读问题之间的某个时间点,某些过程已经破坏了其中的非 ASCII 字符,因此问题最初是关于其中包含 4 个字符的某个字符串。

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

      存储在 latin1 文本文件中的原始问题有:$1¢2(您可以将 ¢ 替换为任何非 ASCII 字符)

      文件由使用 UTF-8 的程序读取。由于 ¢ 对应的字节无法解释,程序替换它并读取文本$1�2。然后使用 UTF-8 写出此文本,从而在文件中生成 $1\xEF\xBF\xBD2

      然后出现了第三个程序,它读取 latin1 格式的文件,并显示 $1�2

      【讨论】:

        【解决方案5】:

        没有。

        我将使用反证法。

        strlen 计算字节数,因此 strlen 为 4 时,该字符串中需要 正好 4 个字节

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

        我们已经确定:

        1. 有 4 个字节
        2. 一个字符用不少于1个字节表示

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

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

        【讨论】:

          【解决方案6】:

          许多 UTF-8 字符占用几个字节而不是一个。这就是 UTF-8 的构造方式(这就是您可以在一个集合中包含这么多字符的方式)。

          改用mb_strlen()

          【讨论】:

          • 有趣的事实:理论上,utf-8 每个字符最多可以使用 8 个字节,虽然这个 lenth 直到现在还没有使用 - 最大使用长度是一堆四字节字符(比如谱号和一些汉字)。
          • strlen()呢,有没有可能答案小于6?
          • @JonLyles: strlen() 计算字符串中的字节数。如果字符串有 6 个字节,则结果为 6。
          • @Truth。谢谢,它已修复。
          猜你喜欢
          • 2015-01-20
          • 1970-01-01
          • 1970-01-01
          • 2018-08-20
          • 2021-04-04
          • 2015-03-18
          • 2011-10-30
          • 2012-11-07
          相关资源
          最近更新 更多