Java编码总结

一、编码概念总结:

1、概念:

字符集(character set):是一个系统支持的所有抽象字符的集合。
字符(character):是各种文字和符号,包括国家文字、标点符号、图形符号、数字等。

2、常见字符集:

字符集规定了符合对应的二进制代码,至于这个二进制代码如何存储则没有任何规定。就是为每个字符规定一个用来表示该字符的数字,仅此而已。
是一种字符编码规范

  • Unicode:也叫统一字符集,它包含了几乎世界上所有的已经发现且需要使用的字符(如中文、日文、英文、德文等)。
  • ASCII:早期的计算机系统只能处理英文,所以ASCII也就成为了计算机的缺省字符集,包含了英文所需要的所有字符。
  • GB2312:中文字符集,包含ASCII字符集。ASCII部分用单字节表示,剩余部分用双字节表示。
  • GBK:GB2312的扩展,完整包含了GB2312的所有内容。
  • GB18030:GBK字符集的超集,常叫大汉字字符集,也叫CJK(Chinese,Japanese,Korea)字符集,包含了中、日、韩三国语言中的所有字符。

3、常见编码方式:

  • UTF-8(Unicode字符集的编码方式)
  • UTF-16(Unicode字符集的编码方式)
    用2个字节为字符编码,可表示的字符数为2^16=65535
  • UTF-32(Unicode字符集的编码方式)
    用4个字节为字符编码(实际上只用了31位,最高位必须为0),有2^31=2147483648个码位
  • ASCII(ASCII字符集的编码方式)

4、其他:

  • ASCII
    是用来表示英文字符的一种编码规范,每个ASCII字符占用1个字节(8bits)
    ASCII编码可以表示的最大字符数是256

  • UTF:UCS Transformation Format,UCS转换格式
    它是将Unicode编码规则和计算机的实际编码对应起来的一个规则。现在流行的UTF有2种:UTF-8和UTF-16 。
    UTF-16和Unicode本身的编码规范(UCS-2(Unicode-16))是一致的
    UTF-8定义了一种“区间规则”,这种规则可以和ASCII编码保持最大程度的兼容 。

  • UTF-8有点类似于Haffman编码,它将Unicode编码为
    00000000-0000007F的字符,用1 个字节表示
    00000080-000007FF的字符,用2 个字节表示
    00000800-0000FFFF的字符,用3 个字节表示

目前为止Unicode-16规范没有指定FFFF以上的字符,所以UTF-8最多是使用3个字节来表示一个字符。但理论上来说,UTF-8最多需要用6字节表示一个字符。

5、中文编码:

国际上制定了针对中文的统一字符集GBK和GB18030,其中GBK已经在Windows、Linux等多种操作系统中被实现。

  • GBK兼容GB2312,并增加了大量不常用汉字,还加入了几乎所有的Big5中的繁体汉字。但是GBK中的繁体汉字和Big5中的几乎不兼容。
  • GB18030相当于是GBK的超集,比GBK包含的字符更多。据我所知目前还没有操作系统直接支持GB18030。

二、计算机中的编码:

1、说明:

  • 字符必须编码后才能被计算机处理。
  • 内码:计算机使用的缺省编码方式就是计算机的内码。
  • 按照程序员的称呼,GB2312、GBK到GB18030都属于双字节字符集 (DBCS)。
    在DBCS中,GB内码的存储格式始终是big endian,即高位在前。
    GB2312的两个字节的最高位都是1。但符合这个条件的码位只有128*128=16384个。所以GBK和GB18030的低字节最高位都可能不是1。不过这不影响DBCS字符流的解析:在读取DBCS字符流时,只要遇到高位为1的字节,就可以将下两个字节作为一个双字节编码,而不用管低字节的高位是什么。

2、编码规则:

编码规则

根据上面编码规则对照表,进行 UTF-8 编码和解码就简单多了。下面以汉字“汉”为利,具体说明如何进行 UTF-8 编码和解码。

“汉”的 Unicode 码点是 0x6c49(110 1100 0100 1001),通过上面的对照表可以发现,0x0000 6c49 位于第三行的范围,那么得出其格式为 1110xxxx 10xxxxxx 10xxxxxx。接着,从“汉”的二进制数最后一位开始,从后向前依次填充对应格式中的 x,多出的 x 用 0 补上。这样,就得到了“汉”的 UTF-8 编码为 11100110 10110001 10001001,转换成十六进制就是 0xE6 0xB7 0x89。

解码的过程也十分简单:如果一个字节的第一位是 0 ,则说明这个字节对应一个字符;如果一个字节的第一位1,那么连续有多少个 1,就表示该字符占用多少个字节。


示例

三、Java中的字符编码和字符集

1、char字符

  • Java中char类型是16位无符号基本数据类型,用来存储Unicode字符,使用UTF-16编码描述一个代码单元。
  • Unicode代码点的合法范围是 :U+0000到U+10FFFF
    U+0000到U+FFFF称为Basic Multilingual Plane(BMP)
    代码点大于U+FFFF的字符称为增补字符,2个char:一个为高位,一个为低位。

2、String字符串

  • Java字符串由char序列组成
  • String类型的length方法,它返回的是UTF-16编码表示的给定字符串的代码单元的数量
    如果想要得到代码点的数量,可以调用codePointCount()方法,charAt方法返回位于指定位置的代码单元,codePointAt方法则返回指定位置的代码点。
  • Java代码需要编译成class文件后由JVM运行,在class文件里,字符串使用UTF-8编码,保存于常量池中。

4、Big Endian,Little Endian与文本开头的标志

  • 一个字符可能占用多个字节,比如字符0xABCD,如果存储为AB CD,则称为Big Endian;如果存储为 CD AB,则称为Little Endian。
  • 要知道具体是哪种编码方式,需要判断文本开头的标志:


    image.png

5、字节流与字符流

  • InputStream为字节输入流的所有类的超类
  • Reader为读取字符流的抽象类
  • java读取文件的方式分为按字节流读取和按字符流读取,其中InputStream、Reader是这两种读取方式的超类。
  • 其实字符流可以看做是一种包装流,它的底层还是采用字节流来读取字节,然后它使用指定的编码方式将读取字节解码为字符。在读取的时候字符读取每次是读取2个字节,字节流每次读取1个字节。

四、相关面试题:

1、Java中的char是两个字节,如何存UTF-8字符?

  • char是两个字节(16位),是用UTF-16来存储一个代码单元,而UTF-8是可变编码方式,存1到3个字节
  • UTF-8是Unicode字符集的一种常见的编码方式,另一种常见的编码方式是UTF-16(最小单位是2个字节)。


    如何存储字符
  • Unicode通用字符集占两个字节,如“中”
  • Unicode扩展字符集就需要用一对char来表示,如表情“😎”
  • Java中的String的length得到的不是字符数,而是字节数
  • 比如“中”这个字符串,以“UTF-16”的编码方式获得的length长度为4,其中前两个字节表示的是字节序标记,说明是后两个字节要一起解析。
    image.png

    具体的例子见:结合Java详谈字符编码和字符集
    Java9中对字符串做了些优化,字符串长度和字符数不一致未做处理,对字符存储空间做了优化,对Latin(拉丁)字符,还用UTF-16存储,就浪费了一半的空间,就用byte存,就可以节省一半的空间。

资料:
Java:Unicode简介
彻底弄懂 Unicode 编码
结合Java详谈字符编码和字符集
java编码之BASE64
Java中的字节,字符与编码,解码
Java Unicode编码系统

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