# 字符集

  • 字符的集合
  • 字符集,绝大部分也可以视作是字符编码,编码表
    • 早期,字符被编号后,存储时就按照编号的方式存储即可,没有encoding的过程。unicode出现后,开始拆分二者。

# 常见字符集

字节数 名称/别名 字符容量 背景
1 ASCII字符集 128 最早用于7bit电传打字机上
1 Extended ASCII字符/Latin 128~256 公司、国家的字符集之间各自为政
1 ISO-8859 128~256 一系列扩充的字符集,包括版本1到版本16,常见的为ISO-8859-1
2 GB2312 6763个汉字、682个符号 中国的字符集标准
2 gbk 21003个汉字 与GB2312是兼容的
2/变长 unicode 最多可容纳1114112个字符,即2的21次方 可展示全球所有的字符,并且可以随着时间进行扩展

# unicode字符集

  • 将所有字符安装使用频度划分为17个平面
  • 每个平面有65535个码点,我们常用的字符基本位于第0个平面上;
  • unicode只规定的字符的码点,用什么字节序表示,则涉及到编码方法;
  • 经常所说的unicode为2字节,在大部分情况下正确,但不完全正确。是因为windows,默认的unicode编码就是utf-16,

# 字符集的安装

  • 字符集是系统层面的基本要素;
字符集设置

# 字符编码

# ASCII编码

  • 二进制序列与西文字母一一映射;
  • 基于定长编码表实现

# ISO8859-1

  • 又称为Latin-1
  • 基于定长编码表实现

# GB2312

  • 基于定长编码表实现

# GBK

  • 基于定长编码表实现

# UTF16

  • 定义Unicode字符在计算机中的存取方法;
  • unicode的常用字符均处于第0个平面,因此,Java以UTF-16作为内存的字符存储格式
  • UTF16通过2个字节,或者4个字节自己来表示一个字符,把部分情况下使用2字节代表一个字符(页0),页1到页16需要四字节显示;
  • UTF-16的缺点是西文字符需要两个字节就显示,且西文字符使用的频率非常高
  • UTF-16的输出形式为二进制,如显示为0x4e2d,而对应的unicode\u4e2d

# UTF8

  • 对不同范围的字符使用不同长度的编码;
  • UTF8编码通过,1字节,2字节,3字节或4字节表示一个字符
unicode编码(16进制) utf-8字节流(2进制)
00000000-0000007F 0xxxxxxx
00000080-000007FF 110xxxxx 10xxxxxx
00000800-0000FFFF 1110xxxx 10xxxxxx 10xxxxxx
00010000-001FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  • 优点是西文字符只占用一个字节,缺点是纯中文环境效率降低;

# UTF32

  • 一个字符由4位组成
  • 所有的unicode字符,均通过4位进行展示,在这个语义下,uncode可视作字符编码

# 字库

  • 字型库,计算机上显示的每个字符(不管哪种语言),都是一个小的图案
  • 字库就是将这些小图案以某种形式保存起来,需要显示的时候还原出来;
  • 感觉其与字体是一个概念;

# 字体

  • 定义了字符的图形表示.
  • 字体是字符编码和字符图形的映射
  • 字体是操作系统的概念
  • 如果系统没有字体,那么将不能展示;
字体设置

# java乱码

# 什么时候需要编码

  • 字符与字节相互转换时,均需要编码

# 常见的乱码类型

  • utf-8编码写入,以iso-8859-1解码读取,乱码形如è¿æ¯è¦ä¿å­ç中æå­ç¬¦
  • utf-16编码写入,以iso-8859-1解码读取,则形如?
  • 具体表现如下:
public class Test1 {
    public static void main(String[] args) {
        String s = "中文测试";

        //utf8 -> iso8859-1字节流   iso8859-1字节流 -> utf8  ->utf8字节流 ->utf8
        //????
        System.out.println(new String(s.getBytes(StandardCharsets.ISO_8859_1)));

        //utf8->utf8字节流  utf8字节流 -> utf16  ->utf8字节流 ->utf8
        //귦隇诨꾕
        System.out.println(new String(s.getBytes(),StandardCharsets.UTF_16));

        //utf8->utf16字节流  utf16字节流 ->utf8  ->utf8字节流 ->utf8
        //��N-e�mK��
        System.out.println(new String(s.getBytes(StandardCharsets.UTF_16)));

        //utf8->utf8字节流  utf8字节流->iso8859_1  ->utf8字节流 ->utf8
        //中文测试
        System.out.println(new String(s.getBytes(StandardCharsets.UTF_8),StandardCharsets.ISO_8859_1));

    }
}

# 编码的原则

  • 对称编解码
  • 特定情况可以在乱码后复原,但是影响因素很多