• lua 中文字符的判断简介


    一般在工作中会遇到中文字符的判断、截断、打码等需求,之前一直没有总结,虽然网上资料也多,今天在这里简单的总结一下。

    1 .UTF-8简单描述

    UTF-8 是 Unicode 的实现方式之一,其对应关系(编码规则)如下表所示:

    Unicode 可以容纳100多万个符号

    UTF-8 最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

    1. 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。取值0-127,与标准ASCII 码一一对应。标准ASCII 码表见附录。
    2. 对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。


    2 .UTF-8的中文字符编码如何生成

    例如 将,两个字从Unicode转换为UTF-8:

    1. 中 : Unicode 是 0x4E2D(0100 1110 0010 1101),根据上表,处于第三行范围内,UTF-8编码需要三个字节,格式为 1110xxxx 10xxxxxx 10xxxxxx
      的Unicode 二进制填充进这个格式,得到 11100100 10111000 10101101,转换为十进制是 228,184,173
      print(string.char(228,184,173)) =>
    2. 龙 : Unicode 是 0x9F99 (1001 1111 1001 1001) ,同样处于第三行范围内。
      UTF-8编码为11101001 10111110 10011001(233,190,153)
      print(string.char(233,190,153)) =>

    3. lua判断字符是不是中文

    通常来说,汉字范围从0x4E00到0x9FA5,转换为UTF-8编码为11100100 10111000 10000000(228, 184, 128) 到 11101001 10111110 10100101(233, 190, 165)
    因此,中文UTF-8编码用3个字节表示,要遵守格式:1110xxxx 10xxxxxx 10xxxxxx
    即第一个字节的取值区间为 [11100000, 11110000) = [0xe0, 0xf0) = [224, 240) 左开右闭
    后两个字节的取值区间为[10000000, 10111111] = [0x800xbf] = [128, 191] 开区间



    4.如何取得字节ASCII码 - string.byte()

    • 原型:string.byte (s [, i [, j] ])
    • 解释:函数返回字符s[i], s[i+1], ···, s[j]的内部数字编码(ASCII码),其中参数i的默认值是1,而参数j的默认值是i。



    5.字符是由几个字节组成

    读取第一个字节,在以下区间的代表不同的字节数:

    1. [0, 0xc0) 表示这个字符仅由1个字节构成
    2. [0xc0, 0xe0) 表示这个字符由2个字节构成
    3. [0xe0, 0xf0) 表示这个字符由3个字节构成
    4. [0xf0, 0xff) 表示这个字符由4个字节构成



     

    1. -- 判断utf8字符byte长度
    2. -- [0, 0xc0) 表示这个字符仅由1个字节构成 [0,192)
    3. -- [0xc0, 0xe0) 表示这个字符由2个字节构成 [192,224)
    4. -- [0xe0, 0xf0) 表示这个字符由3个字节构成 [224,240)
    5. -- [0xf0, 0xff) 表示这个字符由4个字节构成 [240,255)
    6. function Utils.getChrSize(char)
    7. if not char then
    8. return 0
    9. elseif char >= 240 then
    10. return 4
    11. elseif char >= 224 then
    12. return 3
    13. elseif char >= 192 then
    14. return 2
    15. elseif char >= 0 then
    16. return 1
    17. end
    18. end

    6.附加几个常用的函数

    我的需求:

    1. -- 把字符串转换成第一个显示后面是**号 如:中国人 -> 中**
    2. function Utils.changeTextExpress(str)
    3. if not str then return str end
    4. local tempStr = ""
    5. local len = string.utf8len(str)
    6. local first = string.byte(str, 1)
    7. local firstLen = sgs.utils.getChrSize(first)
    8. tempStr = string.sub(str, 1,firstLen)
    9. for i=1,len-1 do
    10. tempStr = tempStr .. "*"
    11. end
    12. return tempStr
    13. end

    再附加几个其他的方法:

    1. -- 计算 UTF8 字符串的长度,每一个中文算一个字符
    2. -- @function [parent=#string] utf8len
    3. -- @param string input 输入字符串
    4. -- @return integer#integer 长度
    5. --[[--
    6. 计算 UTF8 字符串的长度,每一个中文算一个字符
    7. ~~~ lua
    8. local input = "你好World"
    9. print(string.utf8len(input))
    10. -- 输出 7
    11. ~~~
    12. ]]
    13. -- end --
    14. function string.utf8len(input)
    15. local len = string.len(input)
    16. local left = len
    17. local cnt = 0
    18. local arr = {0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}
    19. while left ~= 0 do
    20. local tmp = string.byte(input, -left)
    21. local i = #arr
    22. while arr[i] do
    23. if tmp >= arr[i] then
    24. left = left - i
    25. break
    26. end
    27. i = i - 1
    28. end
    29. cnt = cnt + 1
    30. end
    31. return cnt
    32. end
    1. -- 计算utf8字符串字符数, 中文按两个字符计算
    2. function stringTool.utf8len_ChineseInTwo( str )
    3. local len = 0
    4. local currentIndex = 1
    5. while currentIndex <= #str do
    6. local char = string.byte(str, currentIndex)
    7. local charLength = stringTool.chsize(char)
    8. currentIndex = currentIndex + charLength
    9. if charLength > 2 then
    10. len = len + 2
    11. else
    12. len = len +1
    13. end
    14. end
    15. return len
    16. end
    1. --截取字符串,按字符截取
    2. -- str: 要截取的字符串
    3. -- startChar: 开始字符下标,从1开始
    4. -- numChars: 要截取的字符长度
    5. function stringTool.utf8sub( str, startChar, numChars )
    6. local startIndex = 1
    7. while startChar > 1 do
    8. local char = string.byte(str, startIndex)
    9. startIndex = startIndex + stringTool.chsize(char)
    10. startChar = startChar - 1
    11. end
    12. local currentIndex = startIndex
    13. while numChars > 0 and currentIndex <= #str do
    14. local char = string.byte(str, currentIndex)
    15. currentIndex = currentIndex + stringTool.chsize(char)
    16. numChars = numChars -1
    17. end
    18. return str:sub(startIndex, currentIndex - 1), numChars
    19. end

  • 相关阅读:
    Android中内存泄漏的检测,解决方案以及示例
    【Pycharm配置】在Pycharm中配置Jupyter环境
    目前全球生物识别市场规模迅速扩张,虹膜识别技术也发展迅猛
    开箱评测:双十一刚买的云服务器,到底好不好用?
    类与对象---砥柱代码练习篇(c++)
    基于spring boot+ vue开发的位置数据展现和分析平台源码 UWB源码
    多浦乐IPO过会:预计全年营收2亿 拟募资4.9亿
    FVCOM三维水动力、水交换、溢油物质扩散及输运数值模拟丨FVCOM模型流域、海洋水环境数值模拟方法
    base64_encode()和base64_decode(),URL的加密解密详解
    介绍一下js的节流与防抖?
  • 原文地址:https://blog.csdn.net/pyf_914406232/article/details/133641681