【问题标题】:Strlen not returning the correct string length [duplicate]Strlen 没有返回正确的字符串长度 [重复]
【发布时间】:2018-11-27 18:08:54
【问题描述】:

我有一个包含此内容的字符串:

$myString = 'Câmara de Dirigentes Lojistas';

这个字符串有 29 个字符。但是当我调用 strlen 时,它返回 30 !即使我打电话给var_dump($myString),结果也是这样:

114:string 'Câmara de Dirigentes Lojistas' (length=30)

这里发生了什么?也许问题与特殊字符â有关?

【问题讨论】:

  • â 是两个字节。欢迎使用 UTF8,从现在开始使用 mb_strlen() 以及基本上您在侧边栏中看到的所有其他 mb_ 函数。
  • @Sammitch 谢谢,这成功了!

标签: php


【解决方案1】:

这是正确的行为,因为您使用的是 UTF-8 编码。

请在strlen() documentation上查看此说明

注意:

strlen() 返回字节数而不是字符串中的字符数。

由于您的字符串包含多字节字符 (â),PHP 使用两个字节来表示它。

要获得正确的字符串长度,您必须使用mb_strlen() 函数:

mb_strlen("â"); // 1

strlen("â");    // 2

【讨论】:

    【解决方案2】:

    字符串的“长度”有多种定义,因为有多种技巧用于表示世界各地使用的大量重音字符、变体和非字母脚本。

    • 字符串占用的字节数。这是最容易计算的,但并不总是预期的。例如,在 UTF-16 中,每个代码点占用 2 或 4 个字节;在 UTF-8 中,代码点占用 1、2、3 或 4 个字节。这就是 strlen 和大多数 PHP 函数的用途。
    • “代码点”的数量:字符集中的单独符号。这是下一个最简单的,也是下一个最常见的,但通常是字节和“字形”之间的折衷(见下文) - 将é 计为 2 个“字符”特别有用的情况并不多,只是因为它用组合变音符号表示。在 PHP 中,您可以使用 mb_strlen 来计算这些,告诉它您的字符串的字符编码。
    • “字素”的数量:读者可以识别的单独符号。这是最直观的含义,但对计算机来说最难定义。在 PHP 中,您可以使用 grapheme_strlen,只要您确保您的字符串被编码为 UTF-8。

    【讨论】:

    • Pendantry:UTF-16 有时使用 4 个字节。 ;)
    • 也,h̻̫ow͎̝̻̘͎̝̻̘l̵̥͙̩̻̺͍o̡̝̠͖̹͚͉̹nəg̴̴̜̭̠͉̥̜̭̠͉̥͜sə̥̪̥͍̪̥͘t̫͇h̵i͉̬͇͔̟̣sə̗͕̳͔̜sətərəiəgə?̦̝͙̬̳̤̜̕ span>
    • @Sammitch 哎呀,原来如此!
    • @Sammitch 16em ?
    • @TomBlodget 在“用过的 ems”罐子里放了一美元。
    【解决方案3】:

    字符 â 存在问题,因为它是使用不同编码的特殊字符。像这样的字符实际上是双字符,这就是为什么它给出 30 而不是 29

    要解决这个问题,您需要使用 mb_strlen() 和编码

    $myString = 'Câmara de Dirigentes Lojistas';
    
    echo mb_strlen($myString,'utf8')
    

    注意:如果 mb_strlen 未定义,那么您必须在您的 php 设置中启用 mb 扩展

    【讨论】:

    • 我认为“特殊字符”和“双字符”的概念令人困惑。在某些编码中,例如 UTF-16,all 字符占用超过一个字节;在其他标准中,例如 ISO 8859-15,所有可表示的字符都只占用一个字节。没有人真的比其他人更“特别”。
    【解决方案4】:

    有趣的是,â char 存在于扩展 ascii 中,即它可以只用一个字节表示,您可以使用以下代码尝试:

    $str = utf8_decode('Câmara de Dirigentes Lojistas');
    echo 'length is ' . strlen($str);
    

    这将输出length is 29

    如您所见,当 char 不是纯 ascii(127 char ascii 表)时,PHP 会自动采用 UTF-8。

    【讨论】:

    • 首先,没有一种编码叫做“扩展ASCII”;有几种“ASCII 兼容”的 8 位编码,有些可能包含这个字符。其次,PHP 不一定自动采用 UTF-8,这取决于源文件的编码。最后,字符串utf8_decode 命名不当,经常被误用;它假定输入是 UTF-8(它可能不是),并将其转换为 ISO 8859-1,这不是一个特别有用的字符集。您的示例有效,因为您从 UTF-8 编码文件运行它,并且因为 â 恰好存在于 ISO 8859-1 中。
    • @IMSoP 当然有en.wikipedia.org/wiki/Extended_ASCII - Nelson 谈到重音字母。
    • (这里不是我的反对意见)。
    • @FunkFortyNiner 那篇文章将它用作“ASCII 兼容编码”的同义词,并指出它经常被批评为模棱两可和误导。由于这些字符可以有任意数量,因此不可能说任何特定的非 ASCII 字符“存在于扩展 ASCII 中”。比如â肯定不在ISO 8859-5中,但那符合“扩展ASCII”的定义。
    • @IMSoP 是的,我知道。我(作为一个人)一直认为并被证明重音字母是扩展字符集的一部分,只是说
    猜你喜欢
    • 1970-01-01
    • 2015-10-01
    • 2011-05-08
    • 2012-08-07
    • 2014-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多