UTF-8 ── 占 1-4 字节 长度可变的 UTF 万国码 UNICODE 字符集
UTF-8 (8-bit Unicode Transformation Format) 是一种针对 Unicode 的可变长度字符编码,又称 "万国码"。由 Ken Thompson 于 1992 年创建,现已标准化为 RFC 3629。
UTF-8 用 1 至 4 个字节,编码 UNICODE 字符。用在网页上,可在同一页面显示中文简体、繁体及其它语言 (譬如:英文、日文、韩文)。
Java 使用 UTF-16 表示内部文本,并支持用于字符串串行化的非标准修正 UTF-8 编码。
标准 UTF-8 和修正 UTF-8 有两点不同: 01、在修正 UTF-8 中,null 字符会被编码成 2 个字节 (1100000010000000),而不是标准的 1 个字节 (00000000);这样的话,可保证编码后的字符串中,不会嵌入 null 字符。因此,如在类 C 语言中处理字符串,文本不会在第一个 null 字符截断 (C 字符串以 "\0" 结尾)。
02、在标准 UTF-8 编码中,超出基本多语言范围 (BMP:Basic Multilingual Plane) 的字符,会被编码为 4 字节格式;但在修正 UTF-8 编码中,他们由代理编码对 (surrogate pairs) 表示。然后,这些代理编码对在序列中,分别重新编码。结果,标准 UTF-8 编码中需要 4 个字节的字符,在修正后的 UTF-8 编码中,将需要 6 个字节。
优点UTF-8 编码可通过屏蔽位和移位操作快速读写。字符串比较时,strcmp() 和 wcscmp() 的返回结果相同,因此使排序变得更容易。
字节 FF 和 FE 在 UTF-8 编码中永远不会出现,因此,他们可用来表明 UTF-16 或 UTF-32 文本 (见 BOM) UTF-8 是字节顺序无关的。UTF-8 字节顺序在所有系统中都是一样的,因此, UTF-8 实际上并不需要 BOM。
缺点无法从 UNICODE 字符数,判断出 UTF-8 文本的字节数;因为,UTF-8 是一种可变长度编码。
UTF-8 需使用 2 个字节编码,那些用扩展 ASCII 字符集只需 1 个字节的字符 ISO Latin-1 是 UNICODE 的子集;但不是 UTF-8 的子集。
8 位字符的 UTF-8 编码会被 email 网关过滤,因为 internet 信息最初设计为 7 位 ASCII 码。因此产生了 UTF-7 编码。
UTF-8 在它的表示中使用值 100xxxxx 的几率超过 50%,而现存的实现如 ISO 2022、4873、6429 及 8859 系统,会把它错认为是 C1 控制码。因此产生了UTF-7.5 编码。
ASCII
在所有字符集中,最知名的可能要数被称为 ASCII 的 7 位字符集。ASCII 是美国标准信息交换代码 (American Standard Code for Information Interchange) 的缩写,为美国英语通信所设计。ASCII 字符集由 128 个字符组成,包括大小写字母、数字 0-9、标点符号、非打印字符 (换行符、制表符等 4 个) 及控制字符 (退格、响铃等) 组成。
由于 ASCII 字符集是针对英语设计的,当处理带有音调标号 (形如汉语拼音) 的亚洲文字时就会出现问题。因此,创建出了包括 255 个字符的由 ASCII 扩展所得的一些字符集。
其中有一种通常被称为 IBM 字符集,IBM 字符集把值为 128-255 之间的字符,用于画图和画线,及一些特殊欧洲字符。另一种 8 位字符集是 ISO 8859-1 Latin 1,简称为 ISO Latin-1。它把位于 128-255 之间的字符,用于拉丁字母表中特殊语言字符的编码,因此而得名。
UNICODE
欧洲语言不是地球上的唯一语言,因此,亚洲和非洲语言并不能被 8 位字符集所支持。仅汉语字母表 (或 pictograms) 就有 80000 以上个字符。但是把汉语、日语和越南语的一些相似的字符结合起来,在不同的语言中,使不同的字符代表不同的字,这样只用 2 个字节就可以编码地球上几乎所有地区的文字。因此,创建了 UNICODE 编码。
UNICODE 通过增加一个高字节对 ISO Latin-1 字符集进行扩展,当这些高字节位为 0 时,低字节就是 ISO Latin-1 字符。UNICODE 支持欧洲、非洲、中东、亚洲 (包括统一标准的东亚象形汉字和韩国表音文字)。但 UNICODE 并没有提供对诸如Braille、Cherokee、Ethiopic、Khme、Mongolian、Hmong、Tai Lu、Tai Mau 文字的支持。同时,UNICODE 也不支持如 Ahom、Akkadian、Aramaic、Babylonian Cuneiform、Balti、Brahmi、Etruscan、Hittite、Javanese、Numidian、Old Persian Cuneiform、Syrian 之类的古老文字。
UTF
事实证明,对可用 ASCII 表示的字符,使用 UNICODE 并不高效,因为 UNICODE 比 ASCII 占用大一倍的空间,高字节的 0 对 ASCII 来说毫无用处。为解决这个问题,就出现了一些中间格式字符集,他们被称为通用转换格式,即UTF (Unicode Transformation Format)。
常见的 UTF 格式有:UTF-7、UTF-7.5、UTF-8、UTF-16 及 UTF-32。
字符集
如 UNICODE 字符由 2 个字节表示,则编码成 UTF-8 很可能需要 3 个字节。如 UNICODE 字符由 4 个字节表示,则编码成 UTF-8 可能需要 6 个字节。用 4 个或 6 个字节去编码一个 UNICODE 字符可能太多,但很少遇到那样的 UNICODE 字符。
UTF-8 转换表
Unicode/UCS-4 | bit 数 | UTF-8 | byte 数 | 备注 | 0000 ~ 007F
| 0~7
| 0XXX XXXX
| 1
|
| 0080 ~ 07FF
| 8~11
| 110X XXXX
10XX XXXX
| 2
|
| 0800 ~ FFFF
| 12~16
| 1110XXXX
10XX XXXX
10XX XXXX
| 3
| 基本定义范围:0 ~ FFFF
| 1 0000 ~ 1F FFFF
| 17~21
| 1111 0XXX
10XX XXXX
10XX XXXX
10XX XXXX
| 4
| Unicode 6.1 定义范围:0 ~ 10 FFFF
| 20 0000 ~ 3FF FFFF
| 22~26
| 1111 10XX
10XX XXXX
10XX XXXX
10XX XXXX
10XX XXXX
| 5
| 说明:此非 unicode 编码范围,属于 UCS-4 编码
早期规范。UTF-8 可到达 6 字节序列,可覆盖到 31 位元 (通用字符集原来的极限)。尽管如此,2003 年 11 月 UTF-8 被 RFC 3629 重新规范,只能使用原来 Unicode 定义的区域, U+0000 到 U+10FFFF。根据规范,这些字节值将无法出现在合法 UTF-8 序列中。
| 400 0000 ~ 7FFF FFFF
| 27~31
| 1111 110X
10XX XXXX
10XX XXXX
10XX XXXX
10XX XXXX
10XX XXXX
| 6
|
实际表示 ASCII 字符的 UNICODE 字符,将会编码成 1 个字节,且 UTF-8 表示与 ASCII 字符表示是一样的。所有其他 UNICODE 字符转化成 UTF-8,将需要至少 2 个字节。每个字节由一个换码序列开始。第一个字节由唯一的换码序列,n 位连续的 1 加一位 0 组成, 首字节连续的 1 的个数表示字符编码所需的字节数。
Unicode 转换为 UTF-8 时,可将 Unicode 二进制从低位往高位取出二进制数字,每次取 6 位,如上述的二进制就可分别取出为如下示例所示的格式,前面按格式填补,不足 8 位用 0 填补。
注:Unicode 转换为 UTF-8 需要的字节数,可根据这个规则计算:如果 Unicode 小于 0X80(Ascii 字符),则转换后为 1 个字节。否则,转换后的字节数,为 Unicode 二进制位数减 1 再除以 5。
- 示例,UNICODE uCA (1100 1010) 编码成 UTF-8 将需要 2 个字节:
- uCA -> C3 8A
复制代码
过程如下: uCA (1100 1010) 处于 0080 ~ 07FF 之间,从上文转换表可知,对其编码需要 2 bytes (即:两个字节),其对应 UTF-8 格式为: 110X XXXX10XX XXXX。
从此格式中可看到,对其编码还需要 11 位,而uCA (1100 1010) 仅有 8 位,这时需要在其二进制数前补 0 凑成 11 位: 000 1100 1010, 依次填入 110X XXXX 10XX XXXX 的空位中, 即得 1100 0011 1000 1010 (C3 8A)。
同理,UNICODE uF03F (1111 0000 0011 1111) 编码成 UTF-8 将需要 3 个字节:
u F03F -> EF 80 BF,对应格式为:1110XXXX10XX XXXX10XX XXXX,编码还需要 16 位,将1111 0000 0011 1111 (F03F) 依次填入,可得 1110 1111 1000 0000 1011 1111 (EF 80 BF)。
Unicode 16 进制 | Unicode 2 进制 | bit 数 | UTF-8 2 进制 | UTF-8 16 进制 | CA
| 1100 1010
| 8
| 1100 00111000 1010
| C3 8A
| F0 3F
| 11110000 0011 1111
| 16
| 111011111000 00001011 1111
| EF 80 BF
|
版权声明:
本文为独家原创稿件,版权归 德云社区,未经许可不得转载;否则,将追究其法律责任。
|