PHP substr在utf-8字符串上做什么?

PHP substr在utf-8字符串上做什么?,php,string,encoding,Php,String,Encoding,Sammitch提醒我,我用Hexinator二进制编辑器仔细检查了输入,发现输入错误。所以这个问题结束了 _______原始问题:_______ 我有一个UTF-8字符串,如下所示: <?php $str = '收听'; ?> 在二进制中,$str是: E694B6E590AC <?php $a = $str[1]; ?> 或 我得到的是二进制90美元,不是94美元 从$str[0]到$str[5],我得到了新的二进制文件: E590ACE8AFB4 它

Sammitch提醒我,我用Hexinator二进制编辑器仔细检查了输入,发现输入错误。所以这个问题结束了

_______原始问题:_______

我有一个UTF-8字符串,如下所示:

<?php $str = '收听'; ?>

在二进制中,$str是: E694B6E590AC

<?php $a = $str[1]; ?>


我得到的是二进制90美元,不是94美元

从$str[0]到$str[5],我得到了新的二进制文件: E590ACE8AFB4

它们与$str的url编码相同: %E5%90%AC%E8%AF%B4

那么substr在UTF-8$str内部做了什么呢

顺便说一下,我不想使用mb_substr来剪切UTF-8字符串

<?php
/**
 * urlencodes complete string, including alphanumeric characters and multibyte characters
 * @param string $string the string to encode
 */
function urlencode_all($string){
    $chars = array();
    for($i = 0; $i < strlen($string); $i++){
        $char = (string)dechex(ord($string[$i]));
        if(strlen($char)==1) $char = '0'.$char;
        $chars[] = '%'.$char;
    }
    return implode('', $chars);
}
?>
我不明白为什么$str[0]是E5,而不是E6$str[1]是90,而不是94

我还有一个函数,如下所示,它对utf-8字符串执行substr或字符串索引

<?php
/**
 * urlencodes complete string, including alphanumeric characters and multibyte characters
 * @param string $string the string to encode
 */
function urlencode_all($string){
    $chars = array();
    for($i = 0; $i < strlen($string); $i++){
        $char = (string)dechex(ord($string[$i]));
        if(strlen($char)==1) $char = '0'.$char;
        $chars[] = '%'.$char;
    }
    return implode('', $chars);
}
?>

有人能解释一下substr在这里做了什么吗

顺便说一下,我不想使用mb_substr来剪切UTF-8字符串

<?php
/**
 * urlencodes complete string, including alphanumeric characters and multibyte characters
 * @param string $string the string to encode
 */
function urlencode_all($string){
    $chars = array();
    for($i = 0; $i < strlen($string); $i++){
        $char = (string)dechex(ord($string[$i]));
        if(strlen($char)==1) $char = '0'.$char;
        $chars[] = '%'.$char;
    }
    return implode('', $chars);
}
?>
欢迎来到地狱

有两个核心问题:

1.任何UTF码点都可以由UTF8中的1到4个字节组成。 在您的示例中,每个符号都是3字节UTF8序列,但在单个字符串中混合使用任意长度的字节序列是完全有效的。这使得使用
substr()
变得不切实际,因为它以字节数操作

解决方案:使用

2.您看到的任何单个符号都可能由多个代码点组成。 虽然
mb_substr()
可能能够将UTF8字符串分割成单独的代码点,但您有可能通过破坏特定的代码点序列来损坏字符串

本月8日,本月18日,本月18日,本月18日,本月18日,本月18日,本月18日,本月18日,本月18日,本月18日,本月18日,本月18日,本月18日,本月18日,本月18日,本月18日,本月18日,本月18日,本月18日,本月18日,本月8日,本月8日,本月8日,本月8日,本月8日,本月8日,本本月8日,本月8日,本月8日,本月8日,本月8日,本月8日,本月8日,本月8日,本月8日,本月8日,本本本本月,本月,本本月,本月,本本本月,本本本月8日,本本月8日,本本本月8日,本本本月,本本月,本本本月8日,本月8͎y͍̤͠实际上是:

00000000  54 d2 89 cc b2 cc b0 6f  cc a3 cd 95 cd 89 6e cd  |T......o......n.|
00000010  98 79 cd 95 cc a3 cc b9  cd 9a cd 87 cc 97 20 cd  |.y............ .|
00000020  89 cc ba cc 98 cc a3 cc  9f 74 cd 8d cc b9 cc 9f  |.........t......|
00000030  cc 99 68 cc ac cc b0 cc  aa cc ad cc 98 cd 8e cc  |..h.............|
00000040  a5 65 cc 9b cc ae 20 cc  a8 50 cd 95 cd 96 cc a9  |.e.... ..P......|
00000050  6f cd a1 6e cc 9b cd 95  cc a4 cc a5 cc bc cd 94  |o..n............|
00000060  cc a9 cd 8e 79 cd a0 cd  8d cc a4                 |....y......|
解决方案:嗯。。。如果有人知道这件事,请告诉我

据我所知,中文对多个代码点做的不多[虽然我不是专家],所以你可能对
mb\u substr()
没问题。[直到你不在]

最后 如果你想了解UTF8是如何工作的,维基百科上关于UTF8的文章真的很棒,我建议所有需要处理UTF8的人都阅读它


对我有用。看到了吗?您是否认为您的输入字符串根本不是您所认为的,并且输出是有效的?@Sammitch谢谢。我用Hexinator二进制编辑器仔细检查了输入,发现输入错误。所以问题解决了。对于$str,哪个二进制文件是E694B6E590AC,文件内容($file,$str[0]),为什么我得到的是字节E5,而不是第一个字节E6?mb_substr可以。但这里的问题并不是割断一根绳子。