记录九. Unicode字符集
[TOC]
一. 字符集与编码
- charset 是 character set 的简写,即字符集。完成字符到数字的对应
- encoding 是 charset encoding 的简写,即字符集编码,简称编码。完成数字到具体的二进制编码
如果数字到具体的二进制编码,形式只有一种。即字符集与编码为一对一情形,则混为一谈,也都清楚是一个东西
二. Unicode与UTF编码(Unicode Transformation Format)
Unicode字符集,UTF-8 -16 -32 是同一种字符集的不同编码实现
1. Unicode 整个编码过程
存在的两个层面: 字符 –> 码点 –> 具体编码(即具体的二进制数)
2. 涉及的概念
2.1. 码点
1. 简单说明: 码点是一种抽象的数学编号
2. 码点的表示形式与范围
- U+[XX]XXXX 是码点的表示形式,X 代表一个十六制数字,可以有 4-6 位,不足 4 位前补 0 补足 4 位,超过则按是几位就是几位
- 它的范围目前是 U+0000 ~ U+10FFFF,理论大小为 10FFFF+1=110000(十六进制),而FFFF + 1 = 10000,为65536个数,则总范围为 (16 + 1) * 65536 粗略等于 102万
- 按Unicode官方说法,码点范围就这些,以后也不会再扩充
3. 平面: 将前面的17 * 65536大小的部分,每个65536分为一个字符平面,编号从0开始
- 第一个平面称为BMP (Basic Multilingual Plane 基本多语言平面) ,也叫plane 0。码点范围在U+0000 ~ U+FFFF,日常使用的字符绝大多数都落在这个平面
- 其余十六个平面称为SP(Supplementary Planes) 增补平面
在第一个平面BMP中的字符,使用两个字节即可表示。我们的汉字在CJK统一汉字区域(CJK:Chinese, Japanese, and Korean,中日韩)
4. BMP鸟瞰图: 引出代理区概念
5. 代理区(Surrogate Area): 在鸟瞰图的空白部分属于代理区
- 红色部分 D800–DBFF 属于高代理区(High Surrogate Area)
- 蓝色部分 DC00–DFFF 属于低代理区(Low Surrogate Area)
- 各自的大小均为 4×256=1024
- 这两个区域构成一个二维的表格,供1024 1024 = 16 65536,恰好表示16个增补平面的所有字符
- 代理区的作用见下面 UTF-16 (构成代理对)
2.2. UTF-8 -16 -32 具体编码
第一版Unicode统一使用二字节编码,对ASCII 的字符多占一字符。据说是大牛倒腾除了UTF-8,来兼容
1. utf-8
- 变长的编码格式,可兼容ASCII。因为能兼容,所以国际广受欢迎
- 由于是变长格式,为了在解析时不发生歧义,使用了高位作区分,so 在保存中文方面效率不算太好,GBK类的效率会更高,但国际上扩展空间不如 utf-8
- 码点转成编码的规则
2. utf-16
- 可两字节or四字节
- 当字符的码点处于BMP内,则使用两字节
- 其余字符,则使用4字节的代理对来编码
- 由于早期第一版的Unicode的使用,这里utf-16也有一定范围的应用
3. utf-32
- 使用四字节表示,占用空间多,使用不广泛
- Unicode码点最长就24位(3字节),UTF-32给了4字节给了字符集非常大的扩展空间, 这篇文章有描述
在增补平面的码点,到UTF-16四字节的转换: 使用代理对
- 一个高代理区的行 加 一个低代理区的列 的编码即是一个代理对
- 增补平面的字符,对应的码元,会转成四字节的一对代码对
3. 其他相关概念
- UCS-2 (Universal Character Set coded in 2 octets),表示码点与编码字节数之间的关系
- UCS-4
字符集的发展历史
- 美国标准ASCII。1字节,0 ~ 127个数 128个字符
- 由于1字节,还有1位可用。在兼容ASCII基础上,出现了OEM字符集(Original Equipment Manufacturer
原始设备制造商),即不同供应商可能有不同字符集,出现了ISO8859-1 -3 等 - 中文编码GB2312,兼容ASCII。GBK是对GB2312的扩展
- 出现Unicode
4. 语言相关 Java
十六进制数的表示
- 整形表示十六进制数为0x开头
- 字符表示十六进制数以 \u 开头。u为unicode
char、String类型
- char采用了UTF-16的格式,对于超过BMP的字符保存时,会发生异常
- String类型是用char保存字符,Java内部使用UTF-16作为内部编码方式