【问题标题】:Wrong output when using array indexing on UTF-8 string在 UTF-8 字符串上使用数组索引时输出错误
【发布时间】:2011-09-13 00:45:33
【问题描述】:

我在使用 UTF-8 字符串时遇到了问题。我想从字符串中读取单个字符,例如:

$string = "üÜöÖäÄ";
echo $string[0];

我期待看到ü,但我得到了——为什么?

【问题讨论】:

    标签: php arrays string utf-8 char


    【解决方案1】:

    请改用mb_substr($string, 0, 1, 'utf-8') 来获取角色。

    在您的代码中发生的情况是表达式 $string[0] 获取字符串的 UTF-8 编码表示的第一个 字节,因为 PHP 字符串实际上是字节数组(PHP 不内部识别编码)。

    由于字符串中的第一个字符由多个字节组成 (UTF-8 encoding rules),因此您实际上只能获取字符的一部分。此外,这些规则使您检索的字节无效,无法单独作为一个字符,这就是您看到问号的原因。

    mb_substr知道编码规则,所以不会天真地只给你一个字节;它将获得对第一个字符进行编码所需的数量。

    您可以看到 $string[0] 只返回一个字节:

    $string = "üÜöÖäÄ";
    echo strlen($string[0]);
    

    虽然mb_substr 会返回两个字节:

    $string = "üÜöÖäÄ";
    echo strlen(mb_substr($string, 0, 1, 'utf-8'));
    

    而这两个字节实际上只是一个字符(为此需要使用mb_strlen):

    $string = "üÜöÖäÄ";
    echo mb_strlen(mb_substr($string, 0, 1, 'utf-8'), 'utf-8');
    

    最后,正如 Marwelln 在下面指出的那样,如果您使用 mb_internal_encoding 摆脱 'utf-8' 冗余,情况会变得更容易接受:

    $string = "üÜöÖäÄ";
    mb_internal_encoding('utf-8');
    echo mb_strlen(mb_substr($string, 0, 1));
    

    您可以see most of the above in action

    【讨论】:

    • 我推荐使用php.net/manual/en/function.mb-internal-encoding.php 这样你就不需要在每个mb_ 函数中指定'utf-8'。
    • 如果您需要迭代 UTF8 编码的字符串,也可以在这里查看:stackoverflow.com/questions/3666306/…
    • 这是我在任何 UTF-8 迁移指南中从未读过的内容。是因为没有人(除了我们......好吧,不是我!)在(单字节)字符串上使用数组索引?这对我来说是一个相当大的问题,我不明白为什么所有迁移指南都选择忽略它,只是为了让迁移看起来很轻松。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-15
    • 2020-11-17
    • 2014-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多