编码字符集
ASCII:最先出现的编码字符集,包含了大小写的从A到Z和符号,用8位表示,共258个字符,老美一开始只固定了前127个字符(称为半角),而后面127个字符是在计算机在其他欧美国家开始使用时扩展的,是扩展字符集(全角)。
GB2312和GBK:当中国开始使用计算机表示汉字时,ASCII已经没有空间可以给汉字字符填充,所以中国索性把两个连在一起的大于127的ASCII字符当作一个汉字,这个方案称为GB2312;当GB2312不足够表示所有汉字时,中国规定 两个连在一起的第一个字符大于127的两个ASCII字符当作一个汉字,称为GBK方案。因此会出现:一个汉字字符相当于两个英文字符的情况。
Unicode:当计算机在全世界广泛传播时,出现了许多编码字符集,各个编码字符集之间无法相互识别,当同时出现在同一篇文档中会出现乱码。因此国际标准组织ISO出台了一套16位的字符编码方案以总括现有的各个编码字符集, 称为Unicode。在互联网出现之后,ISO规定了每次传输16位的方案称为UTF-16
字符集编码
Unicode是无法用16位表示所有文字字符的,随着不断有文字填充,必将使用更多位表示,这就将导致ASCII中的半角前面许多位都是0,白白浪费了空间。因此出现了Unicode的字符集编码方案
UTF-16:Unicode最开始的编码方案,笼统地用两个字节表示一个字符,不能解决空间浪费的问题
UTF-8:网络每次传输8位,可变长度的编码方案,可由1~4个字节表示一个字符,增加标识符以表示多少个字节表示一个字符,更加自由,解决了空间浪费问题。但也存在问题,有些文字由于增加了多个标识符,导致需要多个字节表示,如一个汉字字符需要三个字节表示。
Java中的编码字符集
I.java.lang.Character类规定了java使用的编码字符集,从java.lang.Character类注释的解读,我们可以知道:
Java使用了Unicode编码字符集,具体来说Java中的字符数值范围是从0X0000到0x10FFFF,而0x0000到0xFFFF支持UTF-16编码方案,称为BMP(Basic Multilingual Plane 基础多语言面);大于0XFFFF的字符即是扩展字符,大小相当于两个char类型字符。
char类型只支持BMP(即UTF-16包含的字符),char类型数据的value是一个Character类型数据,如’\u005CuD840’,它代表的是该char类型数据在Unicode database中指向的字符,即Character类型不等同于char类型, 如Character.isLetter(’\u005CuD840’)返回的是false,因为Character.isLetter(char char)要求的是传入一个char类型的数据,但该语句中传入的是Character类型的数据
int类型除了支持BMP外还支持扩展字符,如 Character.isLetter(0x2F81A)返回的是true,0x2F81A是一个扩展字符的数值.注释原文如下:
* <p>A {@code char} value, therefore, represents Basic
* Multilingual Plane (BMP) code points, including the surrogate
* code points, or code units of the UTF-16 encoding. An
* {@code int} value represents all Unicode code points,
* including supplementary code points. The lower (least significant)
* 21 bits of {@code int} are used to represent Unicode code
* points and the upper (most significant) 11 bits must be zero.
* Unless otherwise specified, the behavior with respect to
* supplementary characters and surrogate {@code char} values is
* as follows:
*
* <ul>
* <li>The methods that only accept a {@code char} value cannot support
* supplementary characters. They treat {@code char} values from the
* surrogate ranges as undefined characters. For example,
* {@code Character.isLetter('\u005CuD840')} returns {@code false}, even though
* this specific value if followed by any low-surrogate value in a string
* would represent a letter.
*
* <li>The methods that accept an {@code int} value support all
* Unicode characters, including supplementary characters. For
* example, {@code Character.isLetter(0x2F81A)} returns
* {@code true} because the code point value represents a letter
* (a CJK ideograph).
* </ul>
*
* <p>In the Java SE API documentation, <em>Unicode code point</em> is
* used for character values in the range between U+0000 and U+10FFFF,
* and <em>Unicode code unit</em> is used for 16-bit
* {@code char} values that are code units of the <em>UTF-16</em>
- II.Character类中提供了判断字符是BMP还是扩展字符的方法
public static final char MIN_VALUE = '\u0000';
public static final char MAX_VALUE = '\uFFFF';
public static final int MIN_CODE_POINT = 0x000000;
public static final int MAX_CODE_POINT = 0X10FFFF;
public static boolean isBmpCodePoint(int codePoint) {
return codePoint >>> 16 == 0;
// Optimized form of:
// codePoint >= MIN_VALUE && codePoint <= MAX_VALUE
// We consistently use logical shift (>>>) to facilitate
// additional runtime optimizations.
}
public static boolean isValidCodePoint(int codePoint) {
// Optimized form of:
// codePoint >= MIN_CODE_POINT && codePoint <= MAX_CODE_POINT
int plane = codePoint >>> 16;
return plane < ((MAX_CODE_POINT + 1) >>> 16);
}
提供了将扩展字符从数值转为字符类型的方法
//从此处我们可以发现,一个扩展字符相当两个char类字符
static void toSurrogates(int codePoint, char[] dst, int index) {
// We write elements "backwards" to guarantee all-or-nothing
dst[index+1] = lowSurrogate(codePoint);
dst[index] = highSurrogate(codePoint);
}
学习内容来自周华健的网课《[9节课征服「字符编码」]》https://edu.51cto.com/sd/1c7de