编码字符集与字符集编码

编码字符集

  • 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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容