utf8编解码详解

# utf8编解码详解及简单应用

  • 编码规则

UTF-8是Unicode的一种实现,是一种变长字节编码方式。对于某一个字符的UTF-8编码,如果只有一个字节则其最高二进制位为0;如果是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的位数,其余各字节均以10开头。UTF-8最多可用到6个字节。
字节数 | 编码 | 二进制
-------- | —
1字节| 0000 0000-0000 007F | 0xxxxxxx
2字节| 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
3字节| 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxx
4字节| 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

  • 规则延伸
  1. 字符的第一个字节范围: 0x00—0x7F(0-127),或者 0xC2—0xF4(194-244); UTF8 是兼容 ascii 的,所以 0~127 就和 ascii 完全一致
  2. 0xC0, 0xC1,0xF5—0xFF(192, 193 和 245-255)不会出现在UTF8编码中
  3. 0x80—0xBF(128-191)只会出现在第二个及随后的编码中(针对多字节编码,如汉字)
  • 延伸详解
    1、单字节编码0-127同assii,编码规则说的很明确
    2、0xC0, 0xC1为什么不会出现在utf8编码中
    首先看二进制编码
    0xC0 | 1100 0000
    0xC1 | 1100 0001
    假设0xC0 出现在第一个字节,那么字节编码如下
    1100 0000 10xx xxxx
    将其转换成unicode编码为 00xx xxxx,完全是单字节编码。同理0xC1。所以这连个编码不出现的原因是,规则不允许
    3、0xF5—0xFF不会出现在编码中,这里在下就真的不理解了。
    0xFF | 1111 1111
    0xFE | 1111 1110
    不会出现我能理解,编码长度最多为6个。但是0xF5 | 11110101 等为什么不会出现? 求大神解惑。在下认为是可以出现的,网上的版本是错误的。
    4、根据编码规则,多字节编码第二位以10开头,所以第二位的编码范围一定是1000 0000 - 1011 1111 即0x80—0xBF(128-191)。同时,首位编码单字节 0-127,多字节 则大于 193。

  • 简单应用,以lua为例子
    1、判断编码长度:
    local str, count = string.gsub(str, "[^\128-\193]", "")
    2、用来把str中的每个字符映射到tab中
    for uchar in string.gfind(str, "[%z\1-\127\194-\244][\128-\191]*") do tab[#tab+1] = uchar end

实际应用中,str可能会是一个非常长的字符串,整个方法的执行十分消耗效率。此时可以使用携程对for循环进行处理

function split(s, f, flag)
  local pattern = "[%z\1-\127\194-\253][\128-\191]*"
  local i = 0
  for b, e in string.gmatch(s, pattern) do
     i = i + 1
     local c = e - b
     f(i, c, b)
   end
end

function charSplit(s)
  return coroutine.wrap(function()
    return split(s, coroutine.yield, flag)
  end)
end

function text2array(text)
  local array = {}
  for i, c, b in charSplit(text) do
    array[i] = c
  end
  return array
end

coroutine.create(f):用函数 f 创建一个协程,返回 thread 类型对象。
coroutine.wrap(f):与前面 coroutine.create 一样,coroutine.wrap 函数也创建一个协程,与前者返回协程本身不同,后者返回一个函数。当调用该函数时,重新执行协程。

关于0xF5—0xFF(245-255)不会出现在UTF8编码中 还请各位大神解惑

关于0xF5—0xFF(245-255)不会出现在UTF8编码中 的说法是正确的
RFC3629定义了utf8的编码定义:1-4字符编码
RFC2279中在unicode2的时候做了变更:将字符范围限制在0000-10FFFF(utf16可访问范围)
10FFFF: 的utf8编码的头为 244.
范围变更参考utf16编码规则。

附录:
https://tools.ietf.org/html/rfc3629

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值