10、Unicode 字符集、utf-8 编码

一、什么是 Unicode – 字符与十六进制数字的映射表


  • Unicode(Universal Coded Character Set:国际编码字符集合) 称:统一码、万国码、单一码。
    • 由统一码联盟开发,是**计算机科学领域里的一项业界标准**。
      • 包括:**字符集、编码方案**等。
  • 目的:
    • 为全球所有文字系统中的每个****字符分配唯一的数字标识(称为 码点codepoint)。
    • 从而实现跨平台、跨语言的统一字符表示。

  • 码点(codepoint)是指与一个编码表中的某个字符对应的代码值
    • 在 Unicode 标准中,码点采用十六进制书写,并加上前缀 U+
  • 示例:
字符码点
AU+0041
BU+0042
****U+6C49
U+4E2D
U+9F98
😊****U+1F60A
  • Unicode最长可以**使用 4 个字节编码**,也就是 32 个 bit 位
    • 理论上能表示** 232 个字符,可以覆盖全球所有文字系统中的每个****字符**。

二、Unicode 的发展


  • 在 1991 年发布了 Unicode 1.0,当时,收集到的字符,仅占用 65536 个**代码值不到一半**的部分。
  • 经过一段时间后,Unicode 中增加了汉语、日语、韩语中的大量表意文字
    • 导致,Unicode 字符超过了 65536 个

  • 2024 年 9 月 10 日发布 Unicode 16.0.0 版本,共包含 154998字符
  • Unicode 标准理论最多支持 1114112 个码点(范围 U+0000 ~ U+10FFFF)目前仅使用了约 13.9%

三、Unicode 标准中码点(Code Point)空间的****划分


  • 用于分类管理不同字符集合

  • 码点范围是:U+0000 ~ U+10FFFF****。
    • 共划分 17 个平面0 ~ 10)每个平面 65536 个码点0000 ~ FFFF),总计 1114112 个码点
      • 十六进制下 10 就是 16 。因此,0 ~ 10**** 就是 17 个。
      • 17 * 65536 = 1114112
  • 第 0 个平面:
    • 码点范围:U+0000 ~ U+FFFF(共 65,536 个码点)。
  • 第 1 个平面:
    • 码点范围:U+10000 ~ U+1FFFF(共 65,536 个码点)。
  • 第 2 个平面:
    • 码点范围:U+20000 ~ U+2FFFF(共 65,536 个码点)。
  • 依次类推:
    • ……
  • 第 15 个平面:
    • 码点范围:U+F0000 ~ U+FFFFF(共 65,536 个码点)。
  • 第 16 个平面:
    • 码点范围:U+100000 ~ U+10FFFF(共 65,536 个码点)。

1、基本平面(BMP, Plane 0)

  • 第 0 个平面 也叫 基本平面****。

  • BMP(基本多文种平面) 示意图:

  • Java 中的 char 类型用来存储 Unicode 编码基本平面(BMP范围内的字符****。

2、补充平面(Supplementary Planes)

  • 第 1 ~ 16 个平面 统称 补充平面****。

  • Java 使用 代理对(Surrogate Pair两个 char 组成一个逻辑字符)。
    • 可表示 Unicode 扩展的字符(如:Emoji,U+10000 及以上)。

3、小结

  • 通过这种分层设计
    • Unicode 既保证了常用字符高效处理,又为全球文字符号无限扩展提供了可能。

四、Unicode vs utf-8、utf-16、utf-32


  • Unicode 是一个字符集,给所有的字符分配一个码值
    • 这里面只是分配码值,而不是最后的编码实现
  • Unicode 码点需转换为字节序列才能在计算机中存储/传输
  • utf-8、utf-16、utf-32 是 Unicode 字符集编码实现
    • 即:如何将 Unicode 码点转为字节
    • 它们与字符集字符的总数无关。

1、Unicode 缺点:

  • **常用的文字字符**都是采用 4 个字节 **32 位**编码。
  • 这在进行字符存储网络传输时,消耗的资源是比较大的。
/**
 * Unicode 编码
 *      unicode 编码占用 4 个字节【数字、字母、汉字】。
 *      UTF-8   编码 字母、数字占用一个字节。汉字占用 3 个字节。
 *      gbk     编码 字母、数字占用一个字节。汉字占用 2 个字节。
 *
 * @author zhangxw
 * @since 1.0.0
 */
public class Unicode {
    /**
     * 将字符按照指定编码,转成 十六进制 字符串
     * @param param
     * @param charsetName
     * @return
     */
    public static String getHexString(char param, String charsetName){
        byte[] bytes = null;
        try {
            bytes = String.valueOf(param).getBytes(charsetName);
            // unicode 编码:  [-2, -1, 108, 73]
            // UTF-8   编码:  [-26, -79, -119]
            // UTF-16  编码:  [-2, -1, 108, 73]
            // GBK     编码:  [-70, -70]
            System.out.println(Arrays.toString(bytes));
            StringBuffer buffer = new StringBuffer();
            for (byte b : bytes){
                buffer.append(String.format("%02X", b));
            }
            return buffer.toString();
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }


    public static void main(String[] args) {
        char param = '汉';

        // 6C49
        System.out.println(Integer.toHexString((int)param).toUpperCase()+"\n");

        // FEFF6C49
        System.out.println(getHexString(param, "unicode")+"\n");

        // FFFFFFBA
        System.out.println(String.format("%02X", -70));
        // BA
        System.out.println(String.format("%02X", (byte)-70));
        // BABA
        System.out.println(getHexString(param, "GBK")+"\n");

        // E6B189
        System.out.println(getHexString(param, String.valueOf(StandardCharsets.UTF_8))+"\n");

        // FEFF6C49
        System.out.println(getHexString(param, String.valueOf(StandardCharsets.UTF_16))+"\n");
    }
}

2、UTF

  • 为了**节省存储空间、提高网络传输效率**。
    • 提出了** Unicode 转换格式**(Unicode Transformation Format),简称 UTF
  • UTF-32、UTF-16、UTF-8 都是为了**转换 Unicode 码所制定的各种转换方案编码方式**】。

3、UTF-8、UTF-16、UTF-32 区别

  • 1、UTF 8
    • 可变长的编码方式,长度从 1 个字节到 4 个字节不等。能够完全兼容 ASCII 码。

  • :汉字中,“”的 Unicode 码点为:U+6C49
    • 十六进制 6C49二进制 0110 1100 0100 1001
    • 按 UTF-8 三字节格式填充
    • 11100110 10110001 10001001 → 十六进制 E6 B1 89
  • 2、UTF-16
    • 2 个字节 或 4个字节 来表示。
    • unicode 的基本平面(BMP范围内的编码,占用两个字节,char 类型变量也是占用两个字节
      • BMP(基本多文种平面) 范围内的字符使用 UTF-16 编码,占用 2 个字节
      • 所以,Java 中的 char 类型使用 UTF-16 编码的代码单元(code unit)来存储字符。

  • 3、UTF-32
    • UTF-32 对 Unicode 中的**每个字符都用 4 个字节来表示**,占用的空间比其他编码要多的多。
    • 正是这个原因,人们才用的很少。
  • 理解:类似于 🍎 的 编码
    • 汉语拼音表示:pingguo 。
    • 英语表示:apple 。

五、总结


  • 1、字符集是多个字符组成的集合
    • 字符编码是把字符集转换为计算机可识别二进制数字转换规则

  • 2、ASCII 字符集和字符编码是美国人最早使用计算机时发明的。
    • 它只包含了英文、标点和一些控制字符。
    • 1 个字节就可以表示。

  • 3、GB2312 字符集和字符编码是中国人制定的汉字字符标准。GB【国标的首字母】
    • 后来又扩展和修订出 GBK 和 GB18030 标准,目前 GB18030 是最全的汉字字符集。
    • 2 个字节就可以表示。

  • 4、Unicode 字符集是为了覆盖世界各国字符文字而制定的。
    • 它的编码规则能够使得任何一个字符都对应一个唯一的二进制码位。

  • 5、由于 Unicode 字符编码是定长编码,每个字符占用的空间较大,对于存储和传输产生很大浪费。
    • 于是推出了 Unicode 转换格式,即 UTF 。
    • UTF-32、UTF-16、UTF-8 都是为了转换 Unicode 码所制定的各种转换方案
      • 它们都是对 Unicode 码点,进行不同的二进制编码。
  • 6、UTF-8 只是 Unicode 的一种实现方式,UTF-8 是编码方式,而 Unicode 是字符集合
  • 7、UTF-8 采用**变长字节进行字符编码,1 到 4 个字节不等**,并且它能够完全兼容 ASCII 码。
    • 根据 Unicode 字符范围进行不同字节的编码方案,大大减少编码字节的大小,提升了使用效率
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值