PHP substr在utf-8字符串上做什么?
Sammitch提醒我,我用Hexinator二进制编辑器仔细检查了输入,发现输入错误。所以这个问题结束了 _______原始问题:_______ 我有一个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 它
<?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可以。但这里的问题并不是割断一根绳子。