编码格式UTF-8

编码格式 UTF-8

背景

        关于字符编码,强烈推荐阮一峰老师的文章《字符编码笔记:ASCII,Unicode 和 UTF-8》http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
        阮老师是从字符编码的发展历程角度阐述,简单讲,美国人在上个世纪60年代规范了ASCII 码(看其全称,American Standard Code for Information Interchange,基于电报码,电报码基于摩斯码),一个字节(第一位为0)编码了128个字符,Enough for English。
        之后,各个国家就在这个基础上,使用第一位对字符集进行扩展。中国的gb家族,如gb2312,使用了两个字节,收录汉字六千多。但毕竟我汉字博大精深,据说8万多(常用三千多而已),gb18030用了4个字节,收了七万多。反正各国编码就是一个字 — 乱。
        Unicode解决了这个问题(Wikipedia:多年筹备规划之后,The Unicode Consortium was incorporated in California on January 3, 1991, and in October 1991, the first volume of the Unicode standard was published.),每一个符号都给予一个独一无二的编码,可容纳百万多个符号(wikipedia:Unicode 11.0, contains a repertoire of 137,439 characters )。按理来说Unicode一统江湖,各门派可以安枕无忧了,不过问题随之而来了,有些字符需要四个字节来存储,而ASCII 码一个字节就够了,都用4个字节那就太浪费了(UTF-32的编码方式,一一对应),如何更灵活地处理这个问题呢?那就必须要考虑Unicode的其它编码实现方式了。
        UTF-8 就是在互联网上使用最广的一种 Unicode 的编码实现方式(wikipedia: By October 2018 accounts for 92.5% of all web pages)。UTF-8 采用可变长的编码方式,使用1~4个字节表示一个符号,具体根据符号对应的Unicode编码长度而调整实现的字节长度。
        关于Unicode及其实现方式还可参考阮老师的另一篇文章《Unicode与JavaScript详解》http://www.ruanyifeng.com/blog/2014/12/unicode.html,其中阐述了JS支持的UCS-2。

UTF-8

        此处很多引用于Wikipedia UTF-8词条https://en.wikipedia.org/wiki/UTF-8
        UTF-8是一种变长的编码方法(Wikipedia: originally designed by Ken Thompson and Rob Pike),字符长度从1个字节到4个字节不等。越是常用的字符,字节越短,最前面的128个字符,只使用1个字节表示,与ASCII码完全相同。

编号范围字节
0x0000 - 0x007F1
0x0080 - 0x07FF2
0x0800 - 0xFFFF3
0x010000 - 0x10FFFF4

        具体如何编码呢?
        UTF-8 的编码规则很简单,只有二条:
        1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。
        2)对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。

Char. number range
(hexadecimal)
UTF-8 octet sequence
(binary)
0000 0000 - 0000 007F0xxxxxxx
0000 0080 - 0000 07FF110xxxxx 10xxxxxx
0000 0800 - 0000 FFFF1110xxxx 10xxxxxx 10xxxxxx
0001 0000 - 0010 FFFF11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

        那么除了标识位,真正可以用来编码的位数为8-(n+1)+6*(n-1)=1+5n(1<n<=4时),7(n=1时)。简单讲1、2、3、4个字节可用于有效编码的位数分别为7、11、16、21。
        因此,“严”的 Unicode 是4E25(100111000100101),15个有效位,必须用三个字节编码为11100100 10111000 10100101,转换为16进制E4B8A5。
wikipedia上的这个图最清楚

Num of bytesBits for code pointFirst code pointLast code pointByte 1Byte 2Byte 3Byte 4
17U+0000U+007F0xxxxxxx
211U+0080U+07FF110xxxxx10xxxxxx
316U+0800U+FFFF1110xxxx10xxxxxx10xxxxxx
421U+10000U+10FFFF11110xxx10xxxxxx10xxxxxx10xxxxxx

下图说明字符编码之间的转换

CharacterUnicodeOctal code pointBinary code pointBinary UTF-8Octal UTF-8Hexadecimal UTF-8
$U+0024044010 01000010010004424
¢U+00A20242000 1010 001011000010 10100010302 242C2 A2
U+09390044710000 1001 0011 100111100000 10100100 10111001340 224 239E0 A4 B9
U+20AC0202540010 0000 1010 110011100010 10000010 10101100342 202 254E2 82 AC
?U+1034802015100 0001 0000 0011 0100 100011110000 10010000 10001101 10001000360 220 215 210F0 90 8D 88
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值