Unicode和UTF-8关系及UTF-8编码规则及过滤Emoji表情

Unicode 是「字符集」

UTF-8 是「编码规则」

 

字符集:为每一个「字符」分配一个K/V表「码位」。(如:key:编码 value:对应的字符)

编码规则:将「码位」转换为字节序列的规则(编码/解码规则)

 

UTF-8是一套以 8 位为一个编码单位的可变长编码(14个字节)。 (

即:某个字符(如“A”)它只有1个字节长度;

某个字符(如“中”),它就有3个字节长度,

再如Emojj表情包,它可能有4个字节长度)。

那如何判断这个字符,到底占了几个字节呢?就是需要从UTF-8的编码说起。

 

1. 一个字节长度的字符,字节的第一位都为0,和ASCII码完全相同;如(A):01000001

2. n(其中n>1)个字节长度的字符,第一个字节的前n位都为1,第n+1位为0,后面字节的前两位都设为10,这n个字节的其余空位填充该字符unicode码,高位用0补足。

  如:“中”,对应三个字符:11100100 10111000 10101101 -->红色部分为标记位,黑色为数据位;

   -->得到0100 111000 101101 ->0x4E2D ->unicode表,查询是""字。

 

  如果是4个字符的编码就是:11110XXX 10XXXXXX 10XXXXXX 10XXXXXX

 

知道这个规则后,我们就可以用来判断某些文件编码是不是UTF-8编码。或者在mysql编码为utf-8(实际是mysql本身变异的编码,它最长只占3个字节。)时,过滤有4个字节的字符(如Emoji表情编码)。

public static String re(String nickName) {

       StringBuilder sBuilder = new StringBuilder();

       byte[] t1 = nickName.getBytes();

       for (int i = 0; i < t1.length;) {

           byte tt = t1[i];

           int code = 0;

 

           if ((tt & 0x80) == 0x0) {

              // 单字节。

              code = tt;

              i++;

           } else if ((tt & 0xE0) == 0xC0) {

              // 2个字节时:编码 110XXXXX 10XXXXXX

              // 0x1F->11111 ,0x3F 111111

              // t1[i] & 0x1F ->取第一组的后5位,先占到第11-6位置(<<6)

              // t1[i+1] & 0x3F->取第二组的后6)

              code = (((int) (t1[i] & 0x1F)) << 6) | ((int) (t1[i + 1] & 0x3F));

              i += 2;

           } else if ((tt & 0xF0) == 0xE0) {

              // 3个字节时:编码 1110XXXX 10XXXXXX 10XXXXXX

              // 0x0F->1111 ,0x3F 111111

              // t1[i] & 0x0F ->取第一组的后4位,先占到第16-12位置(<<12)

              // t1[i+1] & 0x3F->取第二组的后6位,占到第116位置(<<6)

              // t1[i+2] & 0x3F->取第三组的后6位,

 

              code = (((int) (t1[i] & 0x0F)) << 12) | (((int) (t1[i + 1] & 0x3F)) << 6) | (t1[i + 2] & 0x3F);

              i += 3;

 

           } else if ((tt & 0xF8) == 0xF0) {

              // 4个字节时:编码 11110XXX 10XXXXXX 10XXXXXX 10XXXXXX

             code = (((int) (t1[i] & 0x07)) << 18) | (((int) (t1[i + 1] & 0x3F)) << 12) | (((int) (t1[i + 2] & 0x3F)) << 6) | (t1[i + 3] & 0x3F);

              i += 4;

           }

          if(code!=0) sBuilder.append((char) code);

       }

       return (sBuilder.toString());

    }

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值