需求
如果需要將可能含有中文的字符串進(jìn)行拆分成數(shù)組隔披,我們下面以 utf-8 編碼為例。
解決方案一
我習(xí)慣的方法可能是:
mb_internal_encoding("UTF-8");
$str = "周夢(mèng)康";
$array = [];
for ($i=0,$l = mb_strlen($str); $i < $l; $i++) {
array_push($array, mb_substr($str, $i, 1, "utf-8"));
}
var_export($array);
假如我們沒裝mb
擴(kuò)展怎么辦鸠姨?
解決方案二
今天看到一份代碼铜秆,別人是這么寫的:
function str_split_utf8($str)
{
$split = 1;
$array = array();
for ($i = 0; $i < strlen($str);) {
$value = ord($str[$i]);
if ($value > 127) {
if ($value >= 192 && $value <= 223) {
$split = 2;
} elseif ($value >= 224 && $value <= 239) {
$split = 3;
} elseif ($value >= 240 && $value <= 247) {
$split = 4;
}
} else {
$split = 1;
}
$key = null;
for ($j = 0; $j < $split; $j++, $i++) {
$key .= $str[$i];
}
array_push($array, $key);
}
return $array;
}
代碼解讀
strlen
計(jì)算的是字節(jié)數(shù),而直接使用$str[x]
就沿用了c語言里面char數(shù)組和字符串的習(xí)慣讶迁,表示按字節(jié)來讀取$str
连茧,也就是說每次讀取的數(shù)據(jù)的ascii碼值不可能大于255。而php里使用ord
來獲取ascii碼值巍糯。
切割規(guī)則如下
ascii 碼范圍 | 切割偏移量 |
---|---|
0 ~ 127 | 1 字節(jié) |
192 ~ 223 | 2 字節(jié) |
224 ~ 239 | 3 字節(jié) |
240 ~ 247 | 4 字節(jié) |
為什么呢啸驯?
http://www.ruanyifeng.com/blo...
https://segmentfault.com/a/11... 口語化敘述 utf-8 的來歷
Unicode
Unicode 只是一個(gè)符號(hào)集,它只規(guī)定了符號(hào)的二進(jìn)制代碼祟峦,卻沒有規(guī)定這個(gè)二進(jìn)制代碼應(yīng)該如何存儲(chǔ)罚斗。
UTF-8
UTF-8 就是在互聯(lián)網(wǎng)上使用最廣的一種 Unicode 的實(shí)現(xiàn)方式。UTF-8 最大的一個(gè)特點(diǎn)宅楞,就是它是一種變長(zhǎng)的編碼方式针姿。它可以使用1~4個(gè)字節(jié)表示一個(gè)符號(hào),根據(jù)不同的符號(hào)而變化字節(jié)長(zhǎng)度厌衙。
UTF-8 的編碼規(guī)則很簡(jiǎn)單距淫,只有二條:
- 對(duì)于單字節(jié)的符號(hào),字節(jié)的第一位設(shè)為
0
婶希,后面7
位為這個(gè)符號(hào)的 Unicode 碼榕暇。因此對(duì)于英語字母,UTF-8 編碼和 ASCII 碼是相同的(能容納0~127)喻杈。 - 對(duì)于
n
字節(jié)的符號(hào)(n > 1)拐揭,第一個(gè)字節(jié)的前n
位都設(shè)為1,第n + 1
位設(shè)為0奕塑,后面字節(jié)的前兩位一律設(shè)為10
。剩下的沒有提及的二進(jìn)制位家肯,全部為這個(gè)符號(hào)的 Unicode 碼龄砰。
下表總結(jié)了編碼規(guī)則,字母x
表示可用編碼的位:
Unicode 符號(hào)范圍(十六進(jìn)制) | UTF-8 編碼方式(二進(jìn)制) | UTF-8 首字節(jié)范圍 |
---|---|---|
0000 0000-0000 007F | 0xxxxxxx | 0 ~ 127 |
0000 0080-0000 07FF | 110xxxxx 10xxxxxx | (128+64) ~ (255-32) 也就是 192 ~ 223 |
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx | (128+64+32) ~ (255-16) 也就是 224 ~ 239 |
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | (128+64+32+16) ~ (255-8) 也就是 240 ~ 247 |
想必看了這個(gè)表,大家就能明白了吧换棚。