char到底占几个字节?
两个 (65536个码位, 0 ~ 65535)
这个Unicode它保真吗?
2020-03-10 发布的 Unicode 13.0.0 包含 143,859 个字符.[1]
来做一道简单的比较大小: 143859 和 65536
那么 char
使用的 Unicode 保真吗?
答案是保真的, 接下来简单介绍一下 Unicode 相关知识
哈是Unicode
Unicode, 官方中文名称 统一码, 也被称为 万国码, 是一套通用字符集标准.
起源
国际标准化组织(ISO), 于1984年创建 ISO/IEC JTC1/SC2/WG2 工作组, 希望建立通用字符集(Universal Character Set, UCS), 并最终制定 ISO 10646 标准
统一码联盟, 由 Xerox, Apple 等软件商于1988年成立, 并开发了 Unicode标准(The Unicode Standard)
1991年前后, 两个项目的参与者都认识到, 世界不需要两个不兼容的字符集. 于是, 它们开始合并双方的工作成果, 并为创立一个单一编码表而协同工作. 1991年, 不包含CJK统一汉字集的Unicode 1.0发布. 随后, CJK统一汉字集的制定于1993年完成, 发布了ISO 10646-1:1993, 即Unicode 1.1.
从Unicode 2.0开始, Unicode采用了与ISO 10646-1相同的字库和字码;ISO也承诺, ISO 10646将不会替超出U+10FFFF的UCS-4编码赋值, 以使得两者保持一致. 两个项目仍都独立存在, 并独立地公布各自的标准. 但统一码联盟和ISO/IEC JTC1/SC2都同意保持两者标准的码表兼容, 并紧密地共同调整任何未来的扩展.
平面的概念
随着字符数的增多, Unicode 原有的 16位 空间不够用了, 于是从 Unicode 3.1(2001-03 发布) 开始, 引入了平面(Plane)的概念, 设置了16个辅助平面. 原有的 Unicode 空间称为基本平面(Basic Multilingual Plane, BMP).
平面 | 始末字符值 | 中文名称 | 英文名称 |
---|---|---|---|
0号平面 | U+0000 - U+FFFF | 基本多文种平面 | Basic Multilingual Plane, BMP |
1号平面 | U+10000 - U+1FFFF | 多文种补充平面 | Supplementary Multilingual Plane, SMP |
2号平面 | U+20000 - U+2FFFF | 表意文字补充平面 | Supplementary Ideographic Plane, SIP |
3号平面 | U+30000 - U+3FFFF | 表意文字第三平面 | Tertiary Ideographic Plane, TIP |
4号平面 至 13号平面 |
U+40000 - U+DFFFF | (尚未使用) | |
14号平面 | U+E0000 - U+EFFFF | 特别用途补充平面 | Supplementary Special-purpose Plane, SSP |
15号平面 | U+F0000 - U+FFFFF | 保留作为私人使用区(A区) | Private Use Area-A, PUA-A |
16号平面 | U+100000 - U+10FFFF | 保留作为私人使用区(B区) | Private Use Area-B, PUA-B |
UCS-2 与 UTF-16
ISO 10646 中为 UCS 定义了一种 16位 的编码形式(即 UCS-2), 编码固定占用2个字节, 它包含65536个编码空间.
两个字节显示是不够用的, 于是 UTF-16 来了, 它是一种变长编码, 占用 2 或 4 个字节, 可以表示所有 Unicode 编码.
UTF-16可看成是UCS-2的父集. 在没有辅助平面字符 (surrogate code points) 前, UTF-16与UCS-2所指的是同一的意思. 但当引入辅助平面字符后, 就称为UTF-16了. 现在若有软件声称自己支持UCS-2编码, 那其实是暗指它不能支持在UTF-16中超过2字节的字集. 对于小于0x10000的UCS码, UTF-16编码就等于UCS码.
UTF-16对辅助平面字符的支持是通过一种编码变换实现的, 详见维基:
结论
Java 的上线时间是 1995 年, 此时尚未引入辅助平面, 因此
char
的内码使用的是 UCS-2 编码, 被限定成了
16位.
辅助平面在 2001 年 3 月才随着Unicode 3.1标准发布,
此时已经有上百万的Java程序在运行中, 为了兼容性, Java放弃了将
char
改为 32位 的想法,
转而在标准库中提供相应的方法.
Supplementary Characters in the Java Platform
如何处理增补字符
以下内容主要来自:
Java5.0 (2004-09-30 发布) 中引入了对增补字符的支持, API主要在Character和String类里.
下面用 "𬌗" 字举例.
𬌗 U + 2C317 Dec: 181015
温馨提示: emoji也是Unicode字符哦, 下面以 "😂" 举例
😂 U + 1F602 Dec: 128514
温馨提示: printf() 方法也支持增补字符.
示例如下(此处codePoint是int类型, 表示字符的编码值) 1
System.out.printf("%c", codePoint);
1 |
|