2021-11-11工作问题学习记录

项目中,遇到了一个计算校验中文存储字节数的问题,预期是一个中文字符可以被计算为2个字节,使用的PHP内置方法是 mb_strwidth,但是,有这么一个测试字符串$test_str = "/:;()?@“”。,?!",按照预期的计算值应该为21,本应不能通过校验规则(校验规则是统计字节数超过20,则无法通过校验),然而,实际得到的统计结果却为19,导致通过校验流程后,其他后续处理流程在处理这个字符串后的报错问题,相关代码如下:

<?php
    $test_str = '/:;()?@“”。,?!';
	
	$str_length = mb_strwidth($test_str, 'UTF-8');
	
    // 结果为19,预期结果应该为21
	echo $str_length;

?>

问题原因是中文的前后双引号(“和”)的unicode码分别为\u201c以及\u201d,然而, mb_strwidth对于

字符宽度
U+0000 - U+00190
U+0020 - U+1FFF1
U+2000 - U+FF602
U+FF61 - U+FF9F1
U+FFA0 -2

在U+0020-U+1FFF范围内的字符宽度计算值为1,并不是通常中文和中文标点符号的计算值2,因此,导致了最终的计算值比预期少2的问题现象。我这边参照了前端同学的JS验证算法,做了如下调整:

<?php
    $pattern = '/[^\x00-\xff]/u';
	$replacement = '**';
	$new_str = preg_replace($pattern, $replacement, $test_str);
	$new_str_length = mb_strwidth($new_str, 'UTF-8');
	
    // 结果为21
    echo $new_str_length;

?>

目前测试下来,包括本测试例子在内,大部分的测试用例,均能得到预期的计算统计结果,然而,不清楚这样的调整能否适应更多的场景情形,还需要不断观察总结。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值