----------------基本概念-------------------------------
一.位:
计算机存储信息的最小单位,称之为位(bit),音译比特,二进制的一个“0”或一个“1”叫一位。
二.字节
字节(Byte)是一种计量单位,表示数据量多少,它是计算机信息技术用于计量存储容量的一种计量单位,8个二进制位组成1个字节。在ASCII码中,一个标准英文字母(不分大小写)占一个字节位置,一个标准汉字占二个字节位置。
三.字符
字符是指计算机中使用的文字和符号,比如“1、2、3、A、B、C、~!·#¥%…*()+”等等。
-----------------常用的编码的简单分类(3类)---------------
单字节字符编码:
1. 编码标准:ISO-8859-1
2. 说明:
最简单的编码规则,每一个字节直接作为一个 UNICODE 字符。比如,[0xD6, 0xD0] 这两个字节,通过 iso-8859-1 转化为字符串时,将直接得到 [0x00D6, 0x00D0] 两个 UNICODE 字符,即 "ÖÐ"。
反之,将 UNICODE 字符串通过 iso-8859-1 转化为字节串时,只能正常转化 0~255 范围的字符。
ANSI 编码:
1. 编码标准:GB2312,BIG5,Shift_JIS,ISO-8859-2等
2. 说明:
把 UNICODE 字符串通过 ANSI 编码转化为“字节串”时,根据各自编码的规定,一个 UNICODE 字符可能转化成一个字节或多个字节。
反之,将字节串转化成字符串时,也可能多个字节转化成一个字符。比如,[0xD6, 0xD0] 这两个字节,通过 GB2312 转化为字符串时,将得到 [0x4E2D ] 一个字符,即 '中' 字。
“ANSI 编码”的特点:
1. 这些“ANSI 编码标准”都只能处理各自语言范围之内的 UNICODE 字符。
2. “UNICODE 字符”与“转换出来的字节”之间的关系是人为规定的。
UNICODE 编码:
1. 编码标准:UTF-8,UTF-16(BE),UTF-16(LE)等
2. 说明:
与“ANSI 编码”类似的,把字符串通过 UNICODE 编码转化成“字节串”时,一个 UNICODE 字符可能转化成一个字节或多个字节。
与“ANSI 编码”不同的是:
1. 这些“UNICODE 编码”能够处理所有的 UNICODE 字符。
2. “UNICODE 字符”与“转换出来的字节”之间是可以通过计算得到的。
--------------------------------UTF编码简介---------------------------------
UTF-8:
1. 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。
2. 对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码
3. 一种变长的编码方案,使用 1~6 个字节来存储
Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
--------------------+------------------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0020 0000-03FF FFFF | 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0400 0000-7FFF FFFF | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
UTF-16:
1. 介于 UTF-8 和 UTF-32 之间,使用 2 个或者 4 个字节来存储,长度既固定又可变。
2. 对于 Unicode 编号范围在 0 ~ FFFF 之间的字符,UTF-16 使用两个字节存储,并且直接存储 Unicode 编号,不用进行编码转换
3. 对于 Unicode 编号范围在 10000~10FFFF 之间的字符,UTF-16 使用四个字节存储,具体来说就是:将字符编号的所有比特位分成两部分,较高的一些比特位用一个值介于 D800~DBFF 之间的双字节存储,较低的一些比特位(剩下的比特位)用一个值介于 DC00~DFFF 之间的双字节存储。
4. 位于 0xD800~0xDFFF 之间的 Unicode 编码是特别为四字节的 UTF-16 编码预留的,所以不应该在这个范围内指定任何字符,也就是该范围内在unicode里面不存在对应的unicode编码
5. UTF-16 要求在制定 Unicode 字符集时必须考虑到编码问题,所以真正的 Unicode 字符集也不是随意编排字符的
Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
---------------------+----------------------------------------------------------------------
0000 0000-0000 FFFF | (xxxxxxxx xxxx xxxxx) - (xxxxxxxx xxxxxxxx)
0001 0000-0010 FFFF | (yyyyyyyy yyxxxxxx xxxxxxxx xxxxxxxx) - (110110yy yyyyyyyy 110111xx xxxxxxxx)
UTF-32:
1. 一种固定长度的编码方案,不管字符编号大小,始终使用 4 个字节来存储
2. 以容纳所有的 Unicode 字符,所以直接存储 Unicode 编号即可,不需要任何编码转换。浪费了空间,提高了效率
----------------------名词解释-----------------------
unicode:
1. Unicode是为整合全世界的所有语言文字而诞生的。任何文字在Unicode中都对应一个值, 这个值称为代码点(code point)。代码点的值通常写成 U+ABCD 的格式。
2. Unicode是由美国主要计算机制造商联盟指定的编码字符集,主要用于克服在创建多语言程序和国际化软件时使用的不同编码字符集的混乱。 从版本1.1开始,Unicode严格保持与ISO / IEC 10646及其扩展兼容。 该联盟也是ISO工作的重要贡献者,以进一步发展ISO / IEC 10646
3. CJK就是中日韩的意思。Unicode为了节省码位,将中日韩三国语言中的文字统一编码
ucs-2 & ucs-4:
1. ucs全称是Universal Multiple-Octet Coded Character Set
2. UCS旨在可用于计算机系统和数据通信中的内部数据表示
3. 文字和代码点之间的对应关系就是UCS-2(Universal Character Set coded in 2 octets)。 顾名思义,UCS-2是用两个字节来表示代码点,其取值范围为 U+0000~U+FFFF。
为了能表示更多的文字,人们又提出了UCS-4,即用四个字节表示代码点。 它的范围为 U+00000000~U+7FFFFFFF,其中 U+00000000~U+0000FFFF和UCS-2是一样的。
4. ucs-4结构分为 group plane row cell,每一部分占用一个字节,其中当group和plane为00(16进制)时,是和ucs-2相对应
5. UTF-16是完全对应于UCS-2的
6. UCS-4最高位为0
BMP:
1. 基本多语言面板(Basic Multilingual Plane,简称 BMP)
2. UCS-2 = BMP = plane 00 of group 00
UTF:
1. UCS Transformation Format
2. UTF-8、UTF-16以及UTF-32都是UCS的具体实现,用来存储和传输以及表示
3. UTF-16保存的最小单位为2个字节,UTF-32保存的最小单位为4个字节,所以多字节的编码涉及到字节摆放顺序的问题(大小头)
BOM:
1. Byte Order Mark
2. 是用来标识字节顺序的,只存在于windows平台中,字节流开头的“FFFE”或者“FEFF”也被称为字符"ZERO WIDTH NO-BREAK SPACE"
3. windows平台下的UTF-8编码格式是默认会加上BOM,因为UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式,“FFFE”在UTF-8中的表示为“EF BB BF”(UTF-16的BOM是FEFF),所以如果收到以“EF BB BF”开头的字节流,则表明这是UTF-8编码
4. UTF-16或者UTF-32可以不含有BOM
Big Endian(BE) & Little Endian(LE):
1. ucs-2或者ucs-4中规定的码点在以UTF-16或者UTF-32表示的时候,字节存放顺序的2种
2. 表现为unicode编码的数据中的前2个字节为 "FF FE(Little Endian)",其中windows平台下的默认的Unicode编码为Little Endian的UTF-16
3. 例如“汉”字的Unicode编码是6C49。那么写到文件里时,究竟是将6C写在前面,还是将49写在前 面?如果将6C写在前面,就是Big Endian。如果将49写在前面,就是Little Endian
大端,高位存储在内存地址的低位
小端,低位存储在内存地址的低位
4. unix或者linux相关的平台使用无bom的utf8作为标准的原因是:一切皆文件,一切文件皆是流,一个流可以被任意的切断,独立解析,而不会改变含义。所以它不能有头,也不能有结尾。由于头根本不存在,所以bom不允许存在
5. windows平台使用带BOM的UTF-8编码的原因是:系统缺省都是用户当前代码页(code page),当前代码页不是utf8,这样,utf8作为非当前代码页格式就无法识别
ASCII:
1.美国(国家)信息交换标准(代)码(America Standard Code for Information Interchange)
2.ISO-8859-1是单字节编码,是以8位作为一个表示单元,相当于是ASCII的扩展,是完全兼容ASCII
3.Unicode只与ASCII兼容(更准确地说,是与ISO-8859-1兼容)
ANSI:
1. 美国国家标准协会(American National Standard Institite)
2. ANSI编码是指不同地区或者国家的编码标准,比如GB2312、GBK或者Big-5编码标准,一般都是使用2个字节来表示一个字符,但也有例外,比如GB18030编码标准中的一些汉字是用3个字节表示,不同的ANSI编码是互不兼容的
3. 在windows或者linux中存在内码页(code page)的概念,也就是不同的非unicode编码是存在不同的页的,比如GBK编码在CP936页,UTF-8的代码页是65001
4. 在操作系统内部,比如windows系列的内码就是Unicode编码,是以UTF-16来表示的,只要安装了对应的代码页,则可以正确显示出字符,记事本中选择ANSI编码保存则是使用系统缺省的编码格式存储数据,可以通过修改系统的地区来达到修改缺省的编码格式
5. 内码是指操作系统内部的字符编码,微软一般将缺省代码页指定的编码说成是内码,在确认了内码后,系统将按照当前的缺省代码页去解释文本文件里的字节流
GB2312:
1. 用两个数来编码汉字和中文符号。第一个数称为“区”,第二个数称为“位”。所以也称为区位码
2. GB2312的原文还是区位码,从区位码到内码,需要在高字节和低字节上分别加上A0
3. “啊”的区位码是1601,写成16进制是0x10,0x01。这和计算机广泛使用的ASCII编码冲突。为了兼容00-7f的ASCII编码,我们在区位码的高、低字节上分别加上A0。这样“啊”的编码就成为B0A1,我们将加过两个A0的编码也称为GB2312编码
(从区位码到内码需要在高、低字节上分别加上A0),但是GB2312的原文还是区位码
-----------------误解纠正-----------------------
误解:“ISO-8859-1 是国际编码?”
非也。iso-8859-1 只是单字节字符集中最简单的一种,也就是“字节编号”与“UNICODE 字符编号”一致的那种编码规则。当我们要把一个“字节串”转化成“字符串”,而又不知道它是哪一种 ANSI 编码时,先暂时地把“每一个字节”作为“一个字符”进行转化,不会造成信息丢失。然后再使用 bytes = string.getBytes("iso-8859-1") 的方法可恢复到原始的字节串。
误解:“Java 中,怎样知道某个字符串的内码?”
Java 中,字符串类 java.lang.String 处理的是 UNICODE 字符串,不是 ANSI 字符串。我们只需要把字符串作为“抽象的符号的串”来看待。因此不存在字符串的内码的问题。
当 UNICODE 被支持后,Java 中的 String 是以字符的“序号”来存储的,不是以“某种编码的字节”来存储的,因此已经不存在“字符串的编码”这个概念了。只有在“字符串”与“字节串”转化时,或者,将一个“字节串”当成一个 ANSI 字符串时,才有编码的概念。
用每“一个字节”就是“一个字符”的转化方法,实际上也就等同于采用 ISO-8859-1 进行转化。因此,我们常常使用 bytes = string.getBytes("iso-8859-1") 来进行逆向操作,得到原始的“字节串”。然后再使用正确的 ANSI 编码,比如 string = new String(bytes, "GB2312"),来得到正确的“UNICODE 字符串”。
-------------------------宽字符和窄字符(多字节字符)-------------------------------------
1. 有的编码方式采用 1~n 个字节存储,是变长的,例如 UTF-8、GB2312、GBK 等;如果一个字符使用了这种编码方式,我们就将它称为多字节字符,或者窄字符。
2. 有的编码方式是固定长度的,不管字符编号大小,始终采用 n 个字节存储,例如 UTF-32、UTF-16 等;如果一个字符使用了这种编码方式,我们就将它称为宽字符。
3. Unicode 字符集可以使用窄字符的方式存储,也可以使用宽字符的方式存储;GB2312、GBK、Shift-JIS 等国家编码一般都使用窄字符的方式存储;ASCII 只有一个字节,无所谓窄字符和宽字符。