美文网首页征服Unity3dUnity技术分享Lua
lua 获取UTF-8中文字符串长度-string.byte

lua 获取UTF-8中文字符串长度-string.byte

作者: 云木unity | 来源:发表于2017-12-20 21:17 被阅读107次
    目录:

    一. UTF-8编码规则
    1.1 UTF-8简单描述
    1.2 UTF-8的中文字符编码如何生成
    二、lua 获取UTF-8字符串长度(含中文)
    2.1 lua判断字符是不是中文
    2.2 如何取得字节ASCII码 - string.byte()
    2.3 字符是由几个字节组成
    2.4 获取UTF-8字符串长度(含示例)


    一、UTF-8编码规则

    1.1 UTF-8简单描述

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

    Unicode 可以容纳100多万个符号

    Unicode符号范围 UTF-8字节数 UTF-8编码方式(二进制)
    0000 0000-0000 007F (0-127) 1 0xxxxxxx
    0000 0080-0000 07FF (128-2047) 2 110xxxxx 10xxxxxx
    0000 0800-0000 FFFF (2048-65535) 3 1110xxxx 10xxxxxx 10xxxxxx
    0001 0000-0010 FFFF (65536-1050623) 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

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

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

    1.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)) =>
    input.png out.png

    汉字Unicode码从汉字对应表中查找

    二、lua 获取UTF-8字符串长度(含中文)

    到这里,已经知道UTF-8的字符、中文是怎么生成的了,又出现了2个疑问:

    1. 在lua中怎么判断一个字符是不是中文?
    2. 这个字符是由几个字节组成?

    2.1 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] 开区间

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

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

    2.3 字符是由几个字节组成

    读取第一个字节,在以下区间的代表不同的字节数:(有疑问看1.1表)

    1. [0, 0xc0) 表示这个字符仅由1个字节构成
    2. [0xc0, 0xe0) 表示这个字符由2个字节构成
    3. [0xe0, 0xf0) 表示这个字符由3个字节构成
    4. [0xf0, 0xff) 表示这个字符由4个字节构成
    local function Bytes4Character(theByte)
        local seperate = {0, 0xc0, 0xe0, 0xf0}
        for i = #seperate, 1, -1 do
            if theByte >= seperate[i] then return i end
        end
        return 1
    end
    

    2.4 获取UTF-8字符串长度

    function characters(utf8Str, aChineseCharBytes)
        aChineseCharBytes = aChineseCharBytes or 2
        local i = 1
        local characterSum = 0
        while (i <= #utf8Str) do      -- 编码的关系
            local bytes4Character = Bytes4Character(string.byte(utf8Str, i))
            characterSum = characterSum + (bytes4Character > aChineseCharBytes and aChineseCharBytes or bytes4Character)
            i = i + bytes4Character
        end
    
        return characterSum
    end
    

    示例: UTF-8字符串:我们We

    1. 每一个中文算一个字符 characters("我们We", 1)

      示例1-代码运行.png
    2. 游戏中希望把一个汉字当做2个字节处理characters("我们We", 2)(因为1个汉字的宽度和2个字母相仿)

    示例-代码运行.png

    附录

    标准ascii码表.jpg

    参考

    1. 阮一峰-字符编码笔记:ASCII,Unicode 和 UTF-8
    2. 汉字对应表
    3. lua匹配UTF-8中文汉字

    相关文章

      网友评论

        本文标题:lua 获取UTF-8中文字符串长度-string.byte

        本文链接:https://www.haomeiwen.com/subject/kjdgwxtx.html