zoukankan      html  css  js  c++  java
  • Unicode、UTF-8、UTF-16和UTF-32的区别

         Unicode是一个巨大的字符集,给世界上所有的字符定义了一个唯一编码。其仅仅规定了每个符号的二进制代码,没有制定细化的存储规则。UTF-8、UTF-16、UTF-32才是Unicode的存储格式定义。

        

    UTF-8

    Unicode符号范围 | UTF-8编码方式

             (十六进制) | (二进制)

    --------------------+---------------------------------------------

    0000 0000-0000 007F | 0xxxxxxx

    0000 0080-0000 07FF | 110xxxxx 10xxxxxx

    0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx

    0001 0000-001F FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

    跟据上表,解读UTF-8编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;

    如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。

     

    Little endian和Big endian

    Unicode码可以采用UCS-2格式直接存储。

    以汉字"严"为例,Unicode码是4E25,需要用两个字节存储,一个字节是4E,另一个字节是25。

    存储的时候,4E在前,25在后,就是Big endian方式;25在前,4E在后,就是Little endian方式。

     

    UCS-2和UCS-4

    Unicode是为整合全世界的所有语言文字而诞生的。任何文字在Unicode中都对应一个值,
    这个值称为代码点(code point)。代码点的值通常写成 U+ABCD 的格式。而文字和代码点之间的对应关系就是UCS-2(Universal Character Set coded in 2 octets)。顾名思义,UCS-2是用两个字节来表示代码点,其取值范围为 U+0000~U+FFFF。

    为了能表示更多的文字,人们又提出了UCS-4,即用四个字节表示代码点。它的范围为 U+00000000~U+7FFFFFFF,其中 U+00000000~U+0000FFFF和UCS-2是一样的。

    要注意,UCS-2和UCS-4只规定了代码点和文字之间的对应关系,并没有规定代码点在计算机中如何存储。规定存储方式的称为UTF(Unicode Transformation Format),其中应用较多的就是UTF-16和UTF-8了。

     

    UTF-16

    UTF-16由RFC2781规定,它使用两个字节来表示一个代码点。

    不难猜到,UTF-16是完全对应于UCS-2的,即把UCS-2规定的代码点通过Big Endian或Little Endian方式直接保存下来。UTF-16包括三种:UTF-16,UTF-16BE(Big Endian),UTF-16LE(Little Endian)。

    UTF-16BE和UTF-16LE不难理解,而UTF-16就需要通过在文件开头以名为BOM(Byte Order Mark)的字符
    来表明文件是Big Endian还是Little Endian。BOM为U+FEFF这个字符。

    其实BOM是个小聪明的想法。由于UCS-2没有定义U+FEFF,因此只要出现 FF FE 或者 FE FF 这样的字节序列,就可以认为它是U+FEFF,并且可以判断出是Big Endian还是Little Endian。

    举个例子。“ABC”这三个字符用各种方式编码后的结果如下:

    UTF-16BE

    00 41 00 42 00 43

    UTF-16LE

    41 00 42 00 43 00

    UTF-16(Big Endian)

    FE FF 00 41 00 42 00 43

    UTF-16(Little Endian)

    FF FE 41 00 42 00 43 00

    UTF-16(不带BOM)

    00 41 00 42 00 43

    Windows平台下默认的Unicode编码为Little Endian的UTF-16(即上述的 FF FE 41 00 42 00 43 00)。
    你可以打开记事本,写上ABC,然后保存,再用二进制编辑器看看它的编码结果。

     

    另外,UTF-16还能表示一部分的UCS-4代码点——U+10000~U+10FFFF。表示算法比较复杂,简单说明如下: 1. 从代码点U中减去0x10000,得到U'。这样U+10000~U+10FFFF就变成了 0x00000~0xFFFFF。
    2. 用20位二进制数表示U'。 U'=yyyyyyyyyyxxxxxxxxxx
    3. 将前10位和后10位用W1和W2表示,W1=110110yyyyyyyyyy,W2=110111xxxxxxxxxx,则 W1 = D800~DBFF,W2 = DC00~DFFF。

    例如,U+12345表示为 D8 08 DF 45(UTF-16BE),或者08 D8 45 DF(UTF-16LE)。

    但是由于这种算法的存在,造成UCS-2中的 U+D800~U+DFFF 变成了无定义的字符。

     

    UTF-32

    UTF-32用四个字节表示代码点,这样就可以完全表示UCS-4的所有代码点,而无需像UTF-16那样使用复杂的算法。
    与UTF-16类似,UTF-32也包括UTF-32、UTF-32BE、UTF-32LE三种编码,UTF-32也同样需要BOM字符。仅用'ABC'举例:

    UTF-32BE

    00 00 00 41 00 00 00 42 00 00 00 43

    UTF-32LE

    41 00 00 00 42 00 00 00 43 00 00 00

    UTF-32(Big Endian)

    00 00 FE FF 00 00 00 41 00 00 00 42 00 00 00 43

    UTF-32(Little Endian)

    FF FE 00 00 41 00 00 00 42 00 00 00 43 00 00 00

    UTF-32(不带BOM)

    00 00 00 41 00 00 00 42 00 00 00 43

  • 相关阅读:
    LOJ 6089 小Y的背包计数问题 —— 前缀和优化DP
    洛谷 P1969 积木大赛 —— 水题
    洛谷 P1965 转圈游戏 —— 快速幂
    洛谷 P1970 花匠 —— DP
    洛谷 P1966 火柴排队 —— 思路
    51Nod 1450 闯关游戏 —— 期望DP
    洛谷 P2312 & bzoj 3751 解方程 —— 取模
    洛谷 P1351 联合权值 —— 树形DP
    NOIP2007 树网的核
    平面最近点对(加强版)
  • 原文地址:https://www.cnblogs.com/icooper/p/4583684.html
Copyright © 2011-2022 走看看