1 ASCII码

  统一规定英语字符与二进制位之间的关系。ASCII码一共规定了128个字符的编码。例如,空格“SPACE”是32(二进制00100000),大写字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号)只占用了一个字节的后面7位,最前面的1位统一规定为0。

  2 非ASCII编码

  表示非英语的其他语言时,128个符号是不够的。例如,在法语中,字母上方有注音符号,无法用ASCII码表示。于是,一些欧洲国家就决定:利用字节中闲置的最高位编入新的符号。例如,法语中的é的编码为130(二进制是10000010)。这样可以表示256个符号。

  但是,不同的国家有不同的字母,因此,哪怕它们都使用256个符号的编码方式,代表的字母却不一样。例如,130在法语编码中代表é,在希伯来语编码中代表字母Gimel (ג),在俄语编码中代表另一个符号。0-127表示的符号是一样的,不一样的是128-255这一段。汉字多达10万左右,需要使用多个字节表示一个汉字。例如,简体中文常见的编码方式是GB2312,使用两个字节表示一个汉字,所以理论上最多可以表示256x256=65536个汉字。虽然都是用多个字节表示一个符号,但是GB类的汉字编码与下面的Unicode和UTF-8是没关系的。

  3 Unicode

  世界上存在多种编码方式,同一个二进制数字可以被解释成不同的符号。之所以电子邮件经常出现乱码,是因为发信人和收信人使用的编码方式不一样。作为所有符号的编码,Unicode纳入了世界上所有的符号,给予每一个符号一个独一无二的编码。它是一个庞大的集合,可以容纳100多万个符号。例如,U+0639表示阿拉伯字母Ain,U+0041表示英语的大写字母A,U+4E25表示汉字严。具体的符号对应表,可以查询http://www.unicode.org/或者汉字对应表

  Unicode的问题

  Unicode只是一个符号集,只规定了符号的二进制编码,但没有规定存储方式。例如,汉字严的Unicode是十六进制数4E25,转换成二进制数足足有15位(100111000100101)即需要2个字节。不同的符号需要的字节数量不同。存在如下2个问题:

  1 如何区别Unicode和ASCII?

  计算机怎么知道3个字节表示一个符号,而不是分别表示3个符号呢?

  2 容易出现空间浪费

  英文字母仅需一个字节。如果Unicode统一规定每个符号用3个或4个字节表示,那么存储英文字母时会出现2个或3个字节全是0,浪费空间。

  于是,出现了Unicode的多种实现方式。

  4 UTF-8

  UTF-8是互联网上使用最广的一种Unicode实现方式。其他实现方式包括UTF-16(字符用2个字节或4个字节表示)和UTF-32(字符用4个字节表示)。UTF-8是一种可变长的编码方式,使用1~4个字节表示一个符号,根据不同的符号调整字节数量。

  UTF-8的编码规则:

  1 对于单字节的符号,字节的第一位设为0,后面7位是这个符号的Unicode编码。因此,对于英语字母,UTF-8编码和ASCII码是相同的。

  2 对于n个字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位均设为10。剩下的二进制位由这个符号的Unicode编码从后向前依次填入,空位补0。

  编码规则总结见下表,字母x表示可编码的位:

  

  以汉字严为例,如何实现UTF-8编码:

  已知严的Unicode是4E25(100111000100101),根据上表,4E25处在第3行的范围内(0000 0800-0000 FFFF),所以严的UTF-8编码需要3个字节,即格式是“1110xxxx 10xxxxxx 10xxxxxx”。然后,从严的最后一个二进制位开始,依次从后向前填入格式中的x,空位补0。于是,严的UTF-8编码是“11100100 10111000 10100101”,转换成十六进制是E4B8A5。

  5 代码点和代码单元

  从Java5开始,代码点(code point)是指与一个编码表中的某个字符对应的代码值。在Unicode标准中,代码点采用十六进制书写,并加上前缀U+,例如U+0041是字母A的代码点。多语言中每个字符用16位表示,称为代码单元(code unit)。在Java中,char类型用UTF-16编码描述一个代码单元。使用代码单元而非字符,与Unicode字符集的增补相关。替代区域(surrogate area)[U+D800~U+DBFF表示第一个代码单元,U+DC00〜U+DFFF表示第二个代码单元]。可以快速知道一个代码单元是一个字符的编码,还是一个辅助字符的第一或第二部分。例如,对于整数集合的数学符号,它的代码点是U+1D568,是用两个代码单元U+D835和U+DD68编码的。

  String的length方法得到的是UTF-16编码对应的代码单元数量,而非字符个数;charAt方法得到的是指定位置的代码单元,而非字符。获取字符个数需要调用codePointCount方法,获取单个字符需要调用codePointAt方法。

  考虑字符串:Ƶ is the set of integers.

  使用UTF-16编码表示Ƶ需要两个代码单元。执行char ch = sentence.charAt(1);语句得到的不是空格,而是第二个代码单元Z。为了避免发生这种情况,请不要使用char类型。

  参考资料

  字符编码笔记:ASCII,Unicode和UTF-8

  深入学习Java中的字符串,代码点和代码单元

Java 字符编码 ASCII、Unicode、UTF-8、代码点和代码单元的更多相关文章

  1. 关于JAVA字符编码:Unicode,ISO-8859-1,GBK,UTF-8编码及相互转换

    我们最初学习计算机的时候,都学过ASCII编码. 但是为了表示各种各样的语言,在计算机技术的发展过程中,逐渐出现了很多不同标准的编码格式, 重要的有Unicode.UTF.ISO-8859-1和中国人 ...

  2. 字符编码 ASCII,Unicode和UTF-8的关系

    转自:http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143166410626 ...

  3. 字符编码 ASCII unicode UTF-8

    字符串也是一种数据类型,但是,字符串比较特殊的是还有一个编码问题. 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.最早的计算机在设计时采用8个比特(bit)作为一个字节(b ...

  4. 【JAVA编码专题】JAVA字符编码系列一:Unicode,GBK,GB2312,UTF-8概念基础

    这两天抽时间又总结/整理了一下各种编码的实际编码方式,和在Java应用中的使用情况,在这里记录下来以便日后参考. 为了构成一个完整的对文字编码的认识和深入把握,以便处理在Java开发过程中遇到的各种问 ...

  5. Java 字符编码(一)Unicode 字符编码

    Java 字符编码(一)Unicode 字符编码 Unicode(http://www.unicode.org/versions/#TUS_Latest_Version) 是一个编码方案,说白了希望给 ...

  6. JAVA字符编码一:Unicode,GBK,GB2312,UTF-8概念基础

    第一篇:JAVA字符编码系列一:Unicode,GBK,GB2312,UTF-8概念基础 来源:holen'blog   对字符编码与Unicode,ISO 10646,UCS,UTF8,UTF16, ...

  7. java字符编码-Unicode编码问题刨根究底

    博客搬家: java字符编码问题 前段时间在读<java核心技术卷一>,遇到一些名词:码点.代码单元等,其实字面意思不难理解,解释如下 码点(code point):Unicode编码表中 ...

  8. 彻底搞清楚字符编码: ASCII, ISO_8859, GB2312,UCS, Unicode, Utf-8

    彻底搞清楚字符编码: ASCII, ISO_8859, GB2312,UCS, Unicode, U 1.ASCII: 0-127(128-255未使用),美国标准 2.IS0-8859-1(lati ...

  9. 【JAVA编码】 JAVA字符编码系列二:Unicode,ISO-8859,GBK,UTF-8编码及相互转换

    http://blog.csdn.net/qinysong/article/details/1179489 这两天抽时间又总结/整理了一下各种编码的实际编码方式,和在Java应用中的使用情况,在这里记 ...

随机推荐

  1. PAT Basic 1073. 多选题常见计分法

    题目内容 多选题常见计分法(20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 批改多选题是比较麻烦的事情,有 ...

  2. error: <item> inner element must either be a resource reference or empty.

    FAQ: Android resource compilation failedOutput: /home/cmm/code/AndroidHttpCapture/app/build/intermed ...

  3. 作为完美主义者(强迫症)如何将linux的eth1网卡修改为eth0网卡

    1:由于你是克隆的虚拟机或者直接就是使用别人的Centos操作系统直接打开到自己本地的虚拟机,网卡可能就是eth1而不是eth0,下面简单写一下如何将eth1修改为eth0,步骤如下所示: 2:如果你 ...

  4. golang 的glide包管理使用技巧教程

    安装glide ➜ wemall git:(master) ✗ go get github.com/Masterminds/glide ➜ wemall git:(master) ✗ go insta ...

  5. CentOS 6.9 NFS安装和配置

    1.安装依赖包 yum install nfs-utils rpcbind -y 2.开机启动 chkconfig rpcbind on chkconfig nfs on 3.创建一个共享目录和加权限 ...

  6. Spring MVC 注解

    概述   Spring MVC是一个采用依赖注入的思想编写.对象的依赖注入Bean的方式可以通过Spring XML里面配置,配置之后的Bean使用时候,无需使用New关键字建立对象.但是如果所有的B ...

  7. ELK 环境搭建1-Elasticsearch

    一.安装前准备 1.节点 192.168.30.41 192.168.30.42 192.168.30.43 2.操作系统: Centos7.5 3.安装包 a.java8: jdk-8u181-li ...

  8. P1220 关路灯 区间dp

    题目描述 某一村庄在一条路线上安装了n盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少).老张就住在这条路中间某一路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关掉这些路灯. 为了给村 ...

  9. Codeforces 1118F1 Tree Cutting (Easy Version) (简单树形DP)

    <题目链接> 题目大意: 给定一棵树,树上的点有0,1,2三中情况,0代表该点无色.现在需要你将这棵树割掉一些边,使得割掉每条边分割成的两部分均最多只含有一种颜色的点,即分割后的两部分不能 ...

  10. Linux学习之RPM包管理-yum管理(十七)

    Linux学习之RPM包管理-yum管理 目录 IP地址配置 网络yum源 yum命令 光盘yum源搭建 IP地址配置 IP+子网掩码就可以在局域网(内网)使用. IP+子网掩码+网关+DNS就可以访 ...