计算机基础——Unicode与UTF-8

Unicode与UTF-8的区别简短来说:Unicode是字符集,UTF-8是编码规则。

广义的Unicode包括了字符集与UTF-8、UTF-16等多种编码规则,此处狭义的将Unicode指代为Unicode字符集。

字符集可以理解为,在Unicode中,一个字符对应着一个惟一的编号,计算机使用此编号来表示这个字符。但是计算机并不是直接使用这个编号的二进制数,主要是为了节省存储空间和宽带流量。

例子

例子:test测试

这些字符在Unicode字符集中的编号分别为:

字符unicode编号(16进制)
t0074
e0065
s0073
t0074
6d4b
8bd5

现在不考虑其他,直接将他们转换为对应的二进制数。

字符unicode编号(16进制)对应的二进制数
t007400000000 01110100
e006500000000 01100101
s007300000000 01110011
t007400000000 01110100
6d4b01101101 01001011
8bd510001011 11010101

可以看到,字符串test测试对应的二进制总共占了12个字节。这样做有个问题,每个英文字母的编号只有第二个字节起作用,第一个字节都是0000 0000,浪费空间。

UTF-8

UTF-8编码规则发挥作用的时候到了,它是一种可变长度的编码规则,根据不同情况可以占用1~4个字节。

当字符编码只占一个字节时,第一个二进制都是0,0xxx xxxx,表示这个字符占一个字节,等同于标准ASCII码。

当字符编码占两个字节时,第一个字节的前两位是11,第三位是0,第二个字节的前两位是10,110x xxxx 10xx xxxx,表示这个字符总共需要占两个字节。

具体规则如下表所示:

字符编码(16进制)占用字节数UTF-8编码
0000~007F一个字节0xxxxxxx
0080~07FF两个字节110xxxxx 10xxxxxx
0800~FFFF三个字节1110xxxx 10xxxxxx 10xxxxxx
1 0000~1F FFFF四个字节11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

使用UTF-8对上面的test测试进行编码。

t的Unicode编号为0074,位于0000~007F,使用一个字节编码,UTF-8编码为:0111 0100。

的Unicode编号为6d4b,位于0800~FFFF,使用三个字节编码。

编码过程如下:(16进制)6d4b->(2进制)0110 1101 0100 1011,将获得的二进制数,从低位开始,从右向左一位位的填入到1110 xxxx 10xx xxxx 10xx xxxx,最终获得的UTF-8编码为:1110 0110 1011 0101 1000 1011.

最终,每个字符的UTF-8编码如下:

字符Unicode编号(16进制)UTF-8编码
t00740111 0100
e00650110 0101
s00730111 0011
t00740111 0100
6d4b11100110 10110101 10001011
8bd511101000 10101111 10010101

test测试使用UTF-8编码最终需要10个字节,比直接使用二进制存储节省了2个字节。

汉字占几个字节

这个问题的答案与采用哪种编码方式有关。以最常用的UTF-8为例,一般常用的汉字都是三个字节,其他不常用汉字用四个字节表示。

byte[] bytes = "测".getBytes("UTF-8");
System.out.println("'测'在UTF-8下占的字节数:" + bytes.length);
for (byte b : bytes) {
    System.out.println(b);
}

在运行前,要将IDE的默认编码格式改为UTF-8。-Dfile.encoding=UTF-8

输出结果为:

'测'在UTF-8下占的字节数:3
-26
-75
-117

接下来分析为什么输出会是这三个数字。

"测"的Unicode编号:6d4b。

(16进制)6d4b->(Unicode)01101101 01001011->(UTF-8)11100110 10110101 10001011

在计算机中,数字都是以补码的形式存储,所以以数字形式显示时,也需要转换。关于补码的知识可以看这篇文章:补码原理

1110 0110->1(001 1001+1) = -26
1011 0101->1(100 1010+1) = -75
1000 1011->1(111 0100+1) = -117

所以"测"字最终输出显示为-26,-75,-117。

下面是UTF-8编码规则下,占四个字节的汉字。

// 四个龍,读作“zhé”
byte[] bytes = "𪚥".getBytes("UTF-8");
System.out.println(bytes.length);
// 4
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值