最近写对接打印机,需要打印小票。在写小票模板时有这么一个需求,商品标题过长时需要换行(添加 <BR> ),这就需要传入的字符,根据规定的字节长度去换行。所以就自己封装了一个函数,它会把一个字符串,以规定字节长度分割成数组。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/**
* @param $str //要分割的字符串
* @param $len //分割的每一段长度(中文占2个字节,英文占1个字节)
* @return array
*/
function arr_substr($str, $len)
{
$arr = str_split_unicode($str);
$count = 0;
$start = 0;
$end = 0;
$group = [];
$result = [];
foreach ($arr as $k => $v) {
$strwidth = mb_strwidth($arr[$k], 'UTF-8');
$count = $count + $strwidth;
if ($count >= $len) {
$start = $end;
$end = $k + 1;
$group[] = $count > $len ? [$start, $end - 1] : [$start, $end];
$count = 0;
}
}

foreach ($group as $k => $v) {
$r = array_slice($arr, $group[$k][0], $group[$k][1] - $group[$k][0]);
$result[] = implode('', $r);
}

if (count($group) > 0) {
$result[] = implode('', array_slice($arr, $group[count($group) - 1][1], $len));
} else {
$result[] = $str;
}
return $result;
}

//解决str_split中文乱码问题
function str_split_unicode($str, $l = 0)
{
if ($l > 0) {
$ret = array();
$len = mb_strlen($str, "UTF-8");
for ($i = 0; $i < $len; $i += $l) {
$ret[] = mb_substr($str, $i, $l, "UTF-8");
}
return $ret;
}
return preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY);
}

返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$str = "Nike耐克官方SB ZOOM BLAZER LOW XT男/女滑板鞋休闲情侣鞋864348";
var_dump(arr_substr($str, 14));


array(5) {
[0]=>
string(18) "Nike耐克官方SB"
[1]=>
string(14) " ZOOM BLAZER L"
[2]=>
string(18) "OW XT男/女滑板" =>>> 把男女中间的 "/" 去掉后为13个字节,但因为下一组中第一个字 "鞋" 为两个字节所以就被排到下一组了
[3]=>
string(20) "鞋休闲情侣鞋86"
[4]=>
string(4) "4348"
}