需求
我做的项目里,遇到这么一个需求:客户用的sql server版本比较老,对中文字符的计数还是停留在1个汉字为2个字符的水平。
分析
都2020年了,怎么还有不用UTF8做字符集的应用的系统呢?
但是也没办法,毕竟客户的需求,是必须要满足的。
python的默认字符集是UTF-8,常规思路是,程序代码通过正则匹配Unicode编码范围,把汉字的个数统计出来,然后再为每个中文字符长度+1。
不过我发现还有一种更简单的方法,仅仅通过减法就能准确算出汉字的长度。
代码示例
# 按照一个汉字为两个字符计数
def chn_length(text):
if text is None:
return 0
lenText = len(text)
lenText_utf8 = len(text.encode('utf-8'))
# utf-8一个汉字占3个字符,减去原计数就是多出来的2/3,再除以2就是增量。再加回去即可
size = int((lenText_utf8 - lenText) / 2 + lenText)
return size
a = '你好啊123'
print(chn_length(a))
# 结果
# 9
讲解
- 首先把目标字符串的长度计算出来,由于python默认utf8编码,一个汉字占1个字符,故此时长度(lenText)为6;
- 显式的,以UTF8编码,转成python字节码,这时每个汉字会占3个字符。那我们再次计算长度(lenText_utf8)为12,即3(汉字个数) x 3 + 3(字母个数);
- lenText_utf8 - lenText 得出的结果就是utf8格式下,多出来的字符数,也就是每个汉字额外占用的2个字符的空间;
- 由于每一个汉字都额外占用2个字符,那我们可以给这些额外长度除以2,也就得出了每个汉字只额外占用1个字符的差量;
- 把差量和lenText相加,就得到了我们需要的,一个汉字占2个字符的结果。
小结
数学很奇妙,我们通过简单的减法运算,就代替了正则匹配汉字unicode码这种效率低下的做法。
核心思想:在unicode编码体系下,一个汉字占3个字符。我们只需要(3-1)/2+1就能得到一个汉字占2个字符的结果。
one more thing
客户又提出,需要我按指定长度截断这段字符,需要注意的是不能出现半个汉字导致的乱码。
其实呢,截断也很简单。
v = '你好123'
x = 3
v.encode("gbk")[0:x].decode("gbk")
其实就是先把字符串按照gbk编码(1个汉字=2个字节),然后截断,然后再用gbk解码即可。
上面运行的结果是:你好1
网友评论