
80欧元 欧元符号
单臂哑铃划船-不卑不亢的近义词
2023年3月3日发(作者:上学了)Java中编码以及Unicode总结
1.基本概念
bit位只能是0或者1
byte字节一个字节是8位,1byte=8bits计算机表示的基本单位
KB,MB,GB,TB,PB是以1024与byte进行换算
进制用符号进行计数十进制、二进制、八进制(011)、十六进制(0xFF)
字符文字和符号的总称
字符集多个字符集合的总称。ASCII字符集、GB2312字符集、GBK字符集、BIG5
字符集、GB18003字符集、Unicode字符集
byte可表示2^8=256个字符的表示
00×000000,0000
10×010000,0001
20×010000,0010
1270×7F0111,1111
-1280×801000,0000
-20xFE1111,1110
-10xFF1111,1111
以补码的形式表示的二进制编码。
-2的表示,2=0000,0010,反码1111,1101,补码=反码+1=11111110
1111,1110表示的就是1111,1110-1=1111,1101,取反就是0000,0010也就是2,所以
就是-2
2.字符集和编码
2.1.字符(Character)
字符(Character)是文字与符号的总称,包括文字、图形符号、数学符号等。
2.2.字符集(CharacterSet)
一组抽象字符的集合就是字符集(CharacterSet)。字符集常常和一种具体的语言文字对
应起来,该文字中的所有字符或者大部分常用字符就构成了该文字的字符集,比如英文字符
集。一组有共同特征的字符也可以组成字符集,比如繁体汉字字符集、日文汉字字符集。字
符集的子集也是字符集。
计算机要处理各种字符,就需要将字符和二进制内码对应起来,这种对应关系就是字
符编码(Encoding)。制定编码首先要确定字符集,并将字符集内的字符排序,然后和二进制
数字对应起来。根据字符集内字符的多少,会确定用几个字节来编码。每种编码都限定了一
个明确的字符集合,叫做被编码过的字符集(CodedCharacterSet),这是字符集的另外一个
含义。通常所说的字符集大多都是指编码字符集(CodedCharacterSet)。
字符集
ASCII(AmericanStandardCodeforInformationInterchange,美国信息互换标准代码)
是基于罗马字母表的一套电脑编码系统。由美国国家标准局(ANSI)制定。
7位,可以表示2^7=128个字符。在计算机的存储单元中,一个ASCII码值占一个字
节(8个二进制位),其最高位(b7)用作奇偶校验位。7位编码的字符集只能支持128个字符,
为了表示更多的欧洲常用字符对ASCII进行了扩展,ASCII扩展字符集使用8位(bits)表示
一个字符,共256字符。
ASCII扩展字符集比ASCII字符集扩充出来的符号包括表格符号、计算符号、希腊字母
和特殊的拉丁符号。
2312字符集
GB2312又称为GB2312-80字符集,全称为《信息交换用汉字编码字符集?基本集》,
由原中国国家标准总局发布,1981年5月1日实施。在中国大陆和新加坡获广泛使用。GB2312
收录简化汉字及一般符号、序号、数字、拉丁字母、日文假名、希腊字母、俄文字母、汉语
拼音符号、汉语注音字母,共7445个图形字符。其中包括6763个汉字,其中一级汉字3755
个,二级汉字3008个;包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔
字母在内的682个全角字符。
GB2312中对所收汉字进行了“分区”处理,每区含有94个汉字/符号。这种表示方式
也称为区位码。各区包含的字符如下:01-09区为特殊符号;16-55区为一级汉字,按拼音
排序;56-87区为二级汉字,按部首/笔画排序;10-15区及88-94区则未有编码。
两个字节中前面的字节为第一字节,后面的字节为第二字节。习惯上称第一字节为“高
字节”,而称第二字节为“低字节”。“高位字节”使用了0xA1-0xF7(把01-87区(88-94区
未有编码)的区号加上0xA0),“低位字节”使用了0xA1-0xFE(把01-94加上0xA0)。
以GB2312字符集的第一个汉字“啊”字为例,它的区号16,位号01,则区位码是
1601,在大多数计算机程序中,高字节和低字节分别加0xA0得到程序的汉字处理编码
0xB0A1。计算公式是:0xB0=0xA0+16,0xA1=0xA0+1。
字符集
GBK全名为汉字内码扩展规范,英文名ChineseInternalCodeSpecification。K即是“扩
展”所对应的汉语拼音(KuoZhan11)中“扩”字的声母。GBK来自中国国家标准代码GB
13000.1-93。GBK:汉字国标扩展码,基本上采用了原来GB2312-80所有的汉字及码位,并涵
盖了原Unicode中所有的汉字20902,总共收录了883个符号,21003个汉字及提供了1894
个造字码位。[(GBKH-0xB0)*0x5E+(GBKL-0xA1)]*(汉字离散后每个汉字点阵所占用的字节)
GBK是GB2312的扩展,是向上兼容的,因此GB2312中的汉字的编码与GBK中汉字
的相同。另外,GBK中还包含繁体字的编码。
GBK中每个汉字仍然包含两个字节,第一个字节的范围是0×81-0xFE(即129-254),
第二个字节的范围是0×40-0xFE(即64-254)。GBK中有码位23940个,包含汉字21003个。
5字符集
又称大五码或五大码,1984年由台湾财团法人信息工业策进会和五间软件公司宏碁
(Acer)、神通(MiTAC)、佳佳、零壹(ZeroOne)、大众(FIC)创立,故称大五码。Big5码的产
生,是因为当时台湾不同厂商各自推出不同的编码,如倚天码、IBMPS55、王安码等,彼此
不能兼容;另一方面,台湾政府当时尚未推出官方的汉字编码,而中国大陆的GB2312编码
亦未有收录繁体中文字。
Big5字符集共收录13,053个中文字,该字符集在中国台湾使用。耐人寻味的是该字符
集重复地收录了两个相同的字:“兀”(0xA461及0xC94A)、“嗀”(0xDCD1及0xDDFC)。
Big5码使用了双字节储存方法,以两个字节来编码一个字。第一个字节称为“高位字
节”,第二个字节称为“低位字节”。高位字节的编码范围0xA1-0xF9,低位字节的编码范围
0×40-0×7E及0xA1-0xFE。各编码范围对应的字符类型如下:0xA140-0xA3BF为标点符号、
希腊字母及特殊符号,另外于0xA259-0xA261,存放了双音节度量衡单位用字:兙兛兞兝兡
兣嗧瓩糎;0xA440-0xC67E为常用汉字,先按笔划再按部首排序;0xC940-0xF9D5为次常用
汉字,亦是先按笔划再按部首排序。
18030字符集
GB18030的全称是GB18030-2000《信息交换用汉字编码字符集基本集的扩充》,是我
国政府于2000年3月17日发布的新的汉字编码国家标准,2001年8月31日后在中国市场
上发布的软件必须符合本标准。GB18030-2000收录了27533个汉字,GB18030-2005收录了
70244个汉字。GB18030的总编码空间超过150万个码位。
GB18030字符集标准解决汉字、日文假名、朝鲜语和中国少数民族文字组成的大字符
集计算机编码问题。该标准的字符总编码空间超过150万个编码位,收录了27484个汉字,
覆盖中文、日文、朝鲜语和中国少数民族文字。满足中国大陆、香港、台湾、日本和韩国等
东亚地区信息交换多文种、大字量、多用途、统一编码格式的要求。并且与Unicode3.0版
本兼容,填补Unicode扩展字符字汇“统一汉字扩展A”的内容。并且与以前的国家字符编
码标准(GB2312,GB13000.1)兼容。
GB18030标准采用单字节、双字节和四字节三种方式对字符编码。单字节部分使用0
×00至0×7F码(对应于ASCII码的相应码)。双字节部分,首字节码从0×81至0×FE,尾
字节码位分别是0×40至0×7E和0×80至0×FE。四字节部分采用GB/T11383未采用的0
×30到0×39作为对双字节编码扩充的后缀,这样扩充的四字节编码,其范围为0×
81308130到0×FE39FE39。其中第一、三个字节编码码位均为0×81至0×FE,第二、四个
字节编码码位均为0×30至0×39。
双字节部分收录内容主要包括GB13000.1全部CJK汉字20902个、有关标点符号、表
意文字描述符13个、增补的汉字和部首/构件80个、双字节编码的欧元符号等。四字节部
分收录了上述双字节字符之外的,包括CJK统一汉字扩充A在内的GB13000.1中的全部字
符。
编码
不同的国家和地区制定了不同的标准,由此产生了GB2312,BIG5,JIS等各自的编码标
准。这些使用2个字节来代表一个字符的各种汉字延伸编码方式,称为ANSI编码。在简
体中文系统下,ANSI编码代表GB2312编码,在日文操作系统下,ANSI编码代表JIS编
码。”DBCS”(DoubleByteCharecterSet双字节字符集)。在DBCS系列标准里,最大的特点
是两字节长的汉字字符和一字节长的英文字符并存于同一套编码方案里,因此他们写的程序
为了支持中文处理,必须要注意字串里的每一个字节的值,如果这个值是大于127的,那么
就认为一个双字节字符集里的字符出现了。
汉字编码范围
名称第一字节第二字节
GB23120xB0-0xF7(176-247)0xA0-0xFE(160-254)
GBK0×81-0xFE(129-254)0×40-0xFE(64-254)
Big50×81-0xFE(129-255)0×40-0×7E(64-126)或者0xA1-0xFE(161-254)
2.3.字符集编码(CharacterSetEncoding)
ASCII,GB2312,GBK,BIG5,GB18030,UCS,Utf-8,utf-16,utf-32都有自己不同的规则,都有自
己的对应规则,但都兼容ASCII。在使用时要注意这些编码相互之间的转换规则。对于没有
转换规则的编码体系之间进行转换只能依靠查编码表进行。
的编码体系
编码
ASCII的编号是ISO-646。
8859编码
ISO8859,全称ISO/IEC8859,是国际标准化组织(ISO)及国际电工委员会(IEC)联合制定
的一系列8位字符集的标准,现时定义了17个字符集。
ISO8859-1(Latin-1)–西欧语言
ISO8859-2(Latin-2)–中欧语言
ISO8859-3(Latin-3)–南欧语言。世界语也可用此字符集显示。
ISO8859-4(Latin-4)–北欧语言
ISO8859-5(Cyrillic)–斯拉夫语言
ISO8859-6(Arabic)–阿拉伯语
ISO8859-7(Greek)–希腊语
ISO8859-8(Hebrew)–希伯来语(视觉顺序)
ISO8859-8-I–希伯来语(逻辑顺序)
ISO8859-9(Latin-5或Turkish)–它把Latin-1的冰岛语字母换走,加入土耳其语字母。
ISO8859-10(Latin-6或Nordic)–北日耳曼语支,用来代替Latin-4。
ISO8859-11(Thai)–泰语,从泰国的TIS620标准字集演化而来。
ISO8859-13(Latin-7或BalticRim)–波罗的语族
ISO8859-14(Latin-8或Celtic)–凯尔特语族
ISO8859-15(Latin-9)–西欧语言,加入Latin-1欠缺的法语及芬兰语重音字母,以及欧元符号。
ISO8859-16(Latin-10)–东南欧语言。主要供罗马尼亚语使用,并加入欧元符号。
10046(UCS)编码与Unicode
:
通用字符集(UniversalCharacterSet,UCS)是由ISO制定的ISO10646(或称ISO/IEC10646)
标准所定义的字符编码方式,采用4字节编码。
e:
Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。
它是制定的编码机制,要将全世界常用文字都函括进去。它
为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文
本转换、处理的要求。1990年开始研发,1994年正式公布。随着计算机工作能力的增强,
Unicode也在面世以来的十多年里得到普及。但自从unicode2.0开始,Unicode采用了与ISO
10646-1相同的字库和字码,ISO也承诺ISO10646将不会给超出0×10FFFF的UCS-4编码赋
值,使得两者保持一致。Unicode的编码方式与ISO10646的通用字符集(UniversalCharacter
Set,UCS)概念相对应,目前的用于实用的Unicode版本对应于UCS-2,使用16位的编码空
间。也就是每个字符占用2个字节,基本满足各种语言的使用。实际上目前版本的Unicode
尚未填充满这16位编码,保留了大量空间作为特殊使用或将来扩展。
:
Unicode的实现方式不同于编码方式。
一个字符的Unicode编码是确定的,但是在实际传输过程中,由于不同系统平台的设
计不一定一致,以及出于节省空间的目的,对Unicode编码的实现方式有所不同。Unicode
的实现方式称为Unicode转换格式(UnicodeTranslationFormat,简称为UTF)。
UTF-8:8bit变长编码,对于大多数常用字符集(ASCII中0~127字符)它只使用单字节,
而对其它常用字符(特别是朝鲜和汉语会意文字),它使用3字节。
UTF-16:16bit编码,是变长码,大致相当于20位编码,值在0×0000到0×10FFFF
之间,基本上就是Unicode编码的实现,与CPU字序有关。
UTF-32:32bit编码,定长编码对应于字符的Unicode表示。
ebigendia:
在Windows系统中保存文本文件时通常可以选择编码为ANSI、Unicode、Unicodebig
endian和UTF-8,这里的ANSI和Unicodebigendia是什么编码呢?
UTF-8以字节为编码单元,没有字节序的问题。UTF-16以两个字节为编码单元,在解
释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。
Unicode规范中推荐的标记字节顺序的方法是BOM(即ByteOrderMark)。
在UCS编码中有一个叫做”ZEROWIDTHNO-BREAKSPACE”的字符,它的编码是FEFF。
而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传
输字节流前,先传输字符”ZEROWIDTHNO-BREAKSPACE”。
如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这
个字节流是Little-Endian的。因此字符”ZEROWIDTHNO-BREAKSPACE”又被称作BOM。
Windows就是使用BOM来标记文本文件的编码方式的。
ge的编码体系
codepage指的是一个经过挑选的以特定顺序排列的字符内码列表,对于早期的单字节
内码的语种,codepage中的内码顺序使得系统可以按照此列表来根据键盘的输入值给出一个
对应的内码.对于双字节内码,则给出的是MultiByte到Unicode的对应表,这样就可以把以
Unicode形式存放的字符转化为相应的字符内码.类似unicode,只是另外一种字符编码方式,
注意ASP和SAP中的codepage的区别。
ASP中:
CodePage的作用,是决定页面以何种编码方式显示动态内容。当页面被服务器处
理之后,页面将以CodePage设定的编码输出到客户端。当然,CodePage的参数
需正确,否则,将产生错误信息“CodePage值无效。指定的CodePage值无效。”
(事件ID:0204)。如果CodePage没有设置,则服务器使用默认的CodePage加载
到你的Session里面,使用程序代码:(ge)可以查看
你当前使用的CodePage。
SAP中:最经常我们使用的读取数据的方法就是使用GUI_UPLOAD这个FM.在这个
FM中有个CODEPAGE,是用来指定代码页的.
SiebelValue
SAPCodepage
Description
CP1252
1100
SAPLatin-1–ISO8859-1–codepage
ISO-8859-2
1402
SAPLatin-2–ISO8859-2
ISO-8859-5
1500
SAPCyrillic–ISO8859-5
CP1254
1610
SAPTurkish–ISO8859-9
CP1253
1700
SAPGreek–ISO8859-7–Notacompletematch
CP1255
1800
SAPHebrew–ISO8859-8–Notacompletematch
CP932
8000
SAPShift-JIS
CP950
8300
SAPTaiwanese
CP936
8400
SAPChinese
CP949
8500
SAPKorean
CP874
8600
SAPThai
e历史
1991年,Unicode联盟与ISO的工作组终于开始讨论Unicode与UCS的合并问题。最
终,两者统一了抽象字符集(即任何一个在Unicode中存在的字符,在UCS中也存在),对
于码空间,两者同意以一百一十万为限,Unicode将码空间扩展到了一百一十万,而UCS将
永久性的不使用一百一十万以后的码位。UCS和Unicode都指的是编码字符集,而不是字符
集编码。
字符集编码决定了如何将一个字符的整数编号对应到一个二进制的整数值,有的编码
方案简单的将该整数值直接作为其在计算机中的表示而存储,例如英文字符就是这样,几乎
所有的字符集编码方案中,英文字母的整数编号与其在计算机内部存储的二进制形式都一
致。当初Unicode与UCS还没成家之时,UCS也是需要人爱,需要人疼的,没有自己的字符
集编码怎么成。UCS-2与UCS-4就扮演了这样的角色。UCS-4与UTF-32除了名字不同以外,
思想完全一样。而UCS-2与UTF-16在对前65536个字符的处理上也完全相同,唯一的区别
只在于UCS-2不支持surrogatepair机制,即是说,UCS-2只能对前65536个字符编码,对
其后的字符毫无办法。
e的编码形式
e字符集
Unicode字符集编码是UniversalMultiple-OctetCodedCharacterSet通用多八位编码字
符集的简称,是由一个名为Unicode学术学会(UnicodeConsortium)的机构制订的字符
编码系统,支持现今世界各种不同语言的书面文本的交换、处理及显示。该编码于1990
年开始研发,1994年正式公布,最新版本是2005年3月31日的Unicode4.1.0。Unicode
是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进
制编码,以满足跨语言、跨平台进行文本转换、处理的要求。Unicode标准始终使用十六进
制数字,而且在书写时在前面加上前缀“U+”,例如字母“A”的编码为004116,所以“A”
的编码书写为“U+0041”。
现在的Unicode码空间为U+0000到U+10FFFF,一共1114112个码位,其中只有1,
112,064个码位是合法的(我来替你做算术,有2048个码位不合法),但并不是说现在的
Unicode就有这么多个字符了,实际上其中很多码位还是空闲的,到Unicode4.0规范为止,
只有96,382个码位被分配了字符(但无论如何,仍比很多人认为的65536个字符要多得
多了)。其中U+0000到U+FFFF的部分被称为基本多语言面(BasicMultilingualPlane,BMP)。
U+10000及以上的字符称为补充字符。在Java中(Java1.5之后),补充字符使用两个char
型变量来表示,这两个char型变量就组成了所谓的surrogatepair(在底层实际上是使用一
个int进行表示的)。第一个char型变量的范围称为“高代理部分”(high-surrogatesrange,
从”uD800到”uDBFF,共1024个码位),第二个char型变量的范围称为low-surrogatesrange
(从”uDC00到”uDFFF,共1024个码位),这样使用surrogatepair可以表示的字符数一共
是1024的平方计1048576个,加上BMP的65536个码位,去掉2048个非法的码位,正好
是1,112,064个码位。
关于Unicode的码空间实际上有一些稍不小心就会让人犯错的地方。比如我们都知道
从U+0000到U+FFFF的部分被称为基本多语言面(BasicMultilingualPlane,BMP),这个范
围内的字符在使用UTF-16编码时,只需要一个char型变量就可以保存。仔细看看这个范围,
应该有65536这么大,因此你会说单字节的UTF-16编码能够表示65536个字符,你也会说
Unicode的基本多语言面包含65536个字符,但是再想想刚才说过的surrogatepair,一个
UTF-16表示的增补字符(再一次的,需要两个char型变量才能表示的字符)怎样才能被正
确的识别为增补字符,而不是两个普通的字符呢?答案你也知道,就是通过看它的第一个
char是不是在高代理范围内,第二个char是不是在低代理范围内来决定,这也意味着,高
代理和低代理所占的共2048个码位(从0xD800到0xDFFF)是不能分配给其他字符的。但
这是对UTF-16这种编码方法而言,而对Unicode这样的字符集呢?在Unicode的编号中,
U+D800到U+DFFF是否有字符分配?答案是也没有!这是典型的字符集为方便编码方法而
做的安排(你问他们这么做的目的?当然是希望基本多语言面中的字符和一个char型的
UTF-16编码的字符能够一一对应,少些麻烦,从中我们也能看出UTF-16与Unicode间很深
的渊源与结合)。也就是说,无论Unicode还是UTF-16编码后的字符,在0×0000至0xFFFF
这个范围内,只有63488个字符。这就好比最初的CPU被勉强拿来做多媒体应用,用得多
了,CPU就不得不修正自己从硬件上对多媒体应用提供支持了。
尽管不情愿,但说到这里总还得扯扯相关的概念:代码点和代码单元。代码点(Code
Point)就是指Unicode中为字符分配的编号,一个字符只占一个代码点,例如我们说到字符
“汉”,它的代码点是U+6C49.代码单元(CodeUnit)则是针对编码方法而言,它指的是编
码方法中对一个字符编码以后所占的最小存储单元。例如UTF-8中,代码单元是一个字节,
因为一个字符可以被编码为1个,2个或者3个4个字节;在UTF-16中,代码单元变成了
两个字节(就是一个char),因为一个字符可以被编码为1个或2个char(你找不到比一个
char还小的UTF-16编码的字符,嘿嘿)。说得再罗嗦一点,一个字符,仅仅对应一个代码点,
但却可能有多个代码单元(即可能被编码为2个char)。以上概念绝非学术化的绕口令,这
意味着当你想以一种统一的方式指定自己使用什么字符的时候,使用代码点(即你告诉你的
程序,你要用Unicode中的第几个字符)总是比使用代码单元更好(因为这样做的话你还得
区分情况,有时候提供一个16进制数字,有时候要提供两个)。
例如我们有一个增补字符???(哈哈,你看到了三个问号对吧?因为我的系统显示
不出这个字符),它在Unicode中的编号是U+2F81A,当在程序中需要使用这个字符的时候,
就可以这样来写:
Strings=f(s(0×2F81A));
char[]chars=Array();
for(charc:chars){
(”%x”,(short)c);
}
后面的for循环把这个字符的UTF-16编码打印了出来,结果是d87edc1a注意到了吗?
这个字符变成了两个char型变量,其中0xd87e就是高代理部分的值,0xdc1a就是低代理的
值。
Unicode字符集编码(UniversalMultiple-OctetCodedCharacterSet)通用多八位编码字
符集的简称,支持世界上超过650种语言的国际字符集。Unicode是一种在计算机上使用的
字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、
跨平台进行文本转换、处理的要求。Unicode标准始终使用十六进制数字,而且在书写时在
前面加上前缀“U+”,字母“A”的编码书写为“U+0041”。
Unicode计划使用了17个平面,一共有17*65536=1114112个码位。在Unicode5.0.0
版本中,已定义的码位只有238605个,分布在平面0、平面1、平面2、平面14、平面15、
平面16。其中平面15和平面16上只是定义了两个各占65534个码位的专用区(PrivateUse
Area),分别是0xF0000-0xFFFFD和0×100000-0×10FFFD。所谓专用区,就是保留给大家放
自定义字符的区域,可以简写为PUA。平面0也有一个专用区:0xE000-0xF8FF,有6400个
码位。平面0的0xD800-0xDFFF,共2048个码位,是一个被称作代理区(Surrogate)的特
殊区域。代理区的目的用两个UTF-16字符表示BMP以外的字符。在介绍UTF-16编码时会
介绍。如前所述在Unicode5.0.0版本中,238605-65534*2-6400-2408=99089。余下的99089
个已定义码位分布在平面0、平面1、平面2和平面14上,它们对应着Unicode目前定义
的99089个字符,其中包括71226个汉字。平面0、平面1、平面2和平面14上分别定义
了52080、3419、43253和337个字符。平面2的43253个字符都是汉字。平面0上定义
了27973个汉字。
编码
早期的Unicode标准有UCS-2、UCS-4的说法。UCS-2用两个字节编码,UCS-4用4个
字节编码。UCS-4根据最高位为0的最高字节分成2^7=128个group。每个group再根据次
高字节分为256个平面(plane)。每个平面根据第3个字节分为256行(row),每行有256
个码位(cell)。group0的平面0被称作BMP(BasicMultilingualPlane)。将UCS-4的BMP去
掉前面的两个零字节就得到了UCS-2。
每个平面有2^16=65536个码位。
编码
Unicode标准的编码字符集的字符编码方案。UTF是UnicodeTranslationFormat,即
把Unicode转做某种格式的意思。UTF-32、UTF-16和UTF-8是Unicode标准的编码字符集
的字符编码方案,UTF-16使用一个或两个未分配的16位代码单元的序列对Unicode代码点
进行编码;UTF-32即将每一个Unicode代码点表示为相同值的32位整数。
在Unicode中:汉字“字”对应的数字是23383。在Unicode中,我们有很多方式将
数字23383表示成程序中的数据,包括:UTF-8、UTF-16、UTF-32。UTF是“UCSTransformation
Format”的缩写,可以翻译成Unicode字符集转换格式,即怎样将Unicode定义的数字转换
成程序数据。例如,“汉字”对应的数字是0×6c49和0×5b57,而编码的程序数据是:
BYTEdata_utf8[]={0xE6,0xB1,0×89,0xE5,0xAD,0×97};//UTF-8编码
WORDdata_utf16[]={0×6c49,0×5b57};//UTF-16编码
DWORDdata_utf32[]={0×6c49,0×5b57};//UTF-32编码
这里用BYTE、WORD、DWORD分别表示无符号8位整数,无符号16位整数和无符号
32位整数。UTF-8、UTF-16、UTF-32分别以BYTE、WORD、DWORD作为编码单位。“汉字”
的UTF-8编码需要6个字节。“汉字”的UTF-16编码需要两个WORD,大小是4个字节。“汉
字”的UTF-32编码需要两个DWORD,大小是8个字节。根据字节序的不同,UTF-16可以
被实现为UTF-16LE或UTF-16BE,UTF-32可以被实现为UTF-32LE或UTF-32BE。下面介绍UTF-8、
UTF-16、UTF-32、字节序和BOM。
-8
UTF-8最多是使用3个字节来表示一个字符。但理论上来说,UTF-8最多需要用6字节
表示一个字符。
0000F的字符,用单个字节来表示;
00000080-000007FF的字符用两个字节表示(中文的编码范围)
00000800-0000FFFF的字符用3字节表示
UTF-8以字节为单位对Unicode进行编码。从Unicode到UTF-8的编码方式如下:
Unicode编码
UTF-8
字节流
(二进制)
备注
000000–00007F
十进制:0-~127
0xxxxxxx7bit与ASCII编码一致
000080–0007FF
十进制:128~2047
110xxxxx10xxxxxx11bit7FF=
000800–00FFFF
十进制:2048~65535
1110xxxx10xxxxxx10xxxxxx16bitFFFF=11111
010000–10FFFF
十进制:65536~1114111
11110xxx10xxxxxx10xxxxxx10xxxxxx21bit10FFFF=
111111111
UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0×00-0×7F之间的字
符,UTF-8编码与ASCII编码完全相同。UTF-8编码的最大长度是4个字节。从上表可以看出,
4字节模板有21个x,即可以容纳21位二进制数字。Unicode的最大码位0×10FFFF也只有
21位。
例1:“汉”字的Unicode编码是0×6C49。0×6C49在0×0800-0xFFFF之间,使用用
3字节模板了:1110xxxx10xxxxxx10xxxxxx。将0×6C49写成二进制是:1001,
用这个比特流依次代替模板中的x,得到:1,即E6B189。
例2:Unicode编码0×20C30在0×010000-0×10FFFF之间,使用用4字节模板了:
11110xxx10xxxxxx10xxxxxx10xxxxxx。将0×20C30写成21位二进制数字(不足21位就在前
面补0):000110000,用这个比特流依次代替模板中的x,得到:11110000
1,即F0A0B0B0。
-16
UTF-16编码以16位无符号整数为单位。我们把Unicode编码记作U。编码规则如下:
如果U<0×10000,U的UTF-16编码就是U对应的16位无符号整数(为书写简便,
下文将16位无符号整数记作WORD)。
如果U≥0×10000,我们先计算U’=U-0×10000,然后将U’写成二进制形式:yyyy
yyyyyyxxxxxxxxxx,U的UTF-16编码(二进制)就是:110110yyyyyyyyyy110111xxxxxxxxxx。
为什么U’可以被写成20个二进制位?Unicode的最大码位是0×10ffff,减去0×
10000后,U’的最大值是0xfffff,所以肯定可以用20个二进制位表示。例如:Unicode编
码0×20C30,减去0×10000后,得到0×10C30,写成二进制是:00110000。
用前10位依次替代模板中的y,用后10位依次替代模板中的x,就得到:1111
1100,即0xD8430xDC30。
按照上述规则,Unicode编码0×10000-0×10FFFF的UTF-16编码有两个WORD,第一
个WORD的高6位是110110,第二个WORD的高6位是110111。可见,第一个WORD的
取值范围(二进制)是1100到1111,即0xD800-0xDBFF。第
二个WORD的取值范围(二进制)是1100到1111,即
0xDC00-0xDFFF。
为了将一个WORD的UTF-16编码与两个WORD的UTF-16编码区分开来,Unicode编
码的设计者将0xD800-0xDFFF保留下来,并称为代理区(Surrogate):
D800-DB7F║HighSurrogates║高位替代
DB80-DBFF║HighPrivateUseSurrogates║高位专用替代
DC00-DFFF║LowSurrogates║低位替代
高位替代就是指这个范围的码位是两个WORD的UTF-16编码的第一个WORD。低位
替代就是指这个范围的码位是两个WORD的UTF-16编码的第二个WORD。那么,高位专用
替代是什么意思?我们来解答这个问题,顺便看看怎么由UTF-16编码推导Unicode编码。
如果一个字符的UTF-16编码的第一个WORD在0xDB80到0xDBFF之间,那么它的
Unicode编码在什么范围内?我们知道第二个WORD的取值范围是0xDC00-0xDFFF,所以这
个字符的UTF-16编码范围应该是0xDB800xDC00到0xDBFF0xDFFF。我们将这个范围写成二
进制:
11000000–11111111
按照编码的相反步骤,取出高低WORD的后10位,并拼在一起,得到
11100000–111111111
即0xe0000-0xfffff,按照编码的相反步骤再加上0×10000,得到0xf0000-0×10ffff。这
就是UTF-16编码的第一个WORD在0xdb80到0xdbff之间的Unicode编码范围,即平面15
和平面16。因为Unicode标准将平面15和平面16都作为专用区,所以0xDB80到0xDBFF
之间的保留码位被称作高位专用替代。
-32
UTF-32编码以32位无符号整数为单位。Unicode的UTF-32编码就是其对应的32位无
符号整数。
4.3.4.字节序
根据字节序的不同,UTF-16可以被实现为UTF-16LE或UTF-16BE,UTF-32可以被实现
为UTF-32LE或UTF-32BE。例如:
Unicode编码
UTF-16LEUTF-16BEUTF32-LEUTF32-BE
0×006C49
496C6C49496C000000006C49
0×020C30
43D830DCD843DC30300C020000020C30
那么,怎么判断字节流的字节序呢?Unicode标准建议用BOM(ByteOrderMark)来
区分字节序,即在传输字节流前,先传输被作为BOM的字符”零宽无中断空格”。这个字
符的编码是FEFF,而反过来的FFFE(UTF-16)和FFFE0000(UTF-32)在Unicode中都是未
定义的码位,不应该出现在实际传输中。下表是各种UTF编码的BOM:
UTF编码
ByteOrderMark
UTF-8EFBBBF
UTF-16LEFFFE
UTF-16BEFEFF
UTF-32LEFFFE0000
UTF-32BE0000FEFF
中使用的Unicode
5.1.内部编码
Java中,字符只以一种形式存在,那就是JVM内部的内部表示,Unicode码编号
(U+0000~U+10FFFF)。JVM的唯一确定一个字符使得一个编码在进入jvm或者从jvm输出
时需要进行编码转换。也就是编码转换只发生在JVM和OS以及网络传输的交互地带,也就
是IO的各种byte或者reader/writer输入输出发生作用的地方。在JVM和OS以及网络流交
互的时间,Reader和Writer只是适用默认编码进行了默认的编码转换,来转换为字符流。
面向字符是指系统文件中的字符和内存中的要一致。而面向字节是要保证系统中的二进制内
容和读入JVM内部的二进制内容要一致。
-16
总共17个平面
0×0000~0×10FFFF1114112-2048=1112064个码位
Unicode已定义的码位是238605个
平面15之定义了占65534个码位的专用区,0xF0000~0xFFFFD。
平面16之定义了占65534个码位的专用区,0×100000~0×10FFFD。
平面0中定义了6400个专有区,0xE0000~0xF8FF。
238605-65534*2-6400-2408=99089余下的分布在平面0、1、2、14上。
平面0上定义了52080个字符;
平面1上定义了3419个字符;
平面2上定义了43253个字符;
平面14上定义了337个字符。
平面2的43253个字符都是汉字,平面0上定义了27973个汉字。
基本平面0×0000~0xFFFF
1~14平面0×10000~0xEFFFF0xD800~0xDBFF高位DCOO~DFFF低位
15平面0xF0000~0xFFFFF0xDB80~0xDBBF高位DCOO~DFFF低位
16平面0×100000~0×10FFFF0xDBC0~0xDBFF高位DCOO~DFFF低位
5.3.高位序列和低位序列的判断
#getBytes(String)的源代码
的源代码,再通过其底层类库的字符集类
terEncoding可以找出Unicode的转换器,是采用ByteUnicode这
个类的,这个类的包是读取这个系统属性拼接字符串反射而来的。
6.常见问题
6.1.通用UTF-8来编码
大量使用国外的开源软件时,UTF-8才是编码界最通用的语言。对英文是单字节、中
文是三字节。在大量的英文存在的情况下高效。
6.2.编码问题时查看
%javahome%/jre/lib/
6.3.语言的编码
C、C++、Python2内部字符串都是使用当前系统默认编码。
Python3、Java内部字符串用Unicode保存。
Ruby有一个内部变量$KCODE用来表示可识别的多字节字符串的编码,变量值为”EUC”
“SJIS”“UTF8″“NONE”之一。$KCODE的值为”EUC”时,将假定字符串或正则表达
式的编码为EUC-JP。同样地,若为”SJIS”时则认定为ShiftJIS。若为”UTF8″时则认定为
UTF-8。若为”NONE”时,将不会识别多字节字符串。在向该变量赋值时,只有第1个字节
起作用,且不区分大小写字母。”e”“E”代表”EUC”,”s”“S”代表“SJIS”,”u”“U”
代表“UTF8″,而”n”“N”则代表“NONE”。默认值为”NONE”。即默认情况下Ruby
把字符串当成单字节序列来处理。
的unicode
6.5.网页编码
一个网页要在浏览器中正常显示,需要保持网页文件的编码、网页的meta标签声明
(charset来制定的其实是encoding编码而不是字符集)、浏览器编码设置是一致的。
6.6.联通乱码
在Win下的新建一个记事本文件,输入”联通”两个字之后,保存之后重新打开,发
现出现乱码。这是因为GBK编码与UTF8编码产生了编码冲突。
从UNICODE到UTF8的转换规则:
UnicodeUTF-8
0000–007F0xxxxxxx
0080–07FF110xxxxx10xxxxxx
0800–FFFF1110xxxx10xxxxxx10xxxxxx
联的Unicode编码是[0x80][0x54]
通的Unicode编码是[0x90][0x1A]
8054和901A在0800-FFFF之间,所以要用3字节模板:1110xxxx10xxxxxx10xxxxxx。
使用第三种转换得到
[0xE8][0x81][0x94][0xE9][0x80][0x9A],这就是其UTF8的编码。
新建一个文本文件时,记事本的编码默认是ANSI,中文的就是GBK编码,而,此时”
联通”的内码是:[0xC1][0xAA][0xCD][0xA8]
C111000001
AA10101010
CD11001101
A810101000
其中联的两个字节、通的两个字节的起始部分的都是”110″和”10″,与UTF8规则
里的两字节模板是一致,所以再次用记事本打开时,记事本误认为这是一个UTF8编码的文
件。按照反编码得到UNICODE的0x006A,和0×0368,0×0368这个字符什么也不是,这
就是”联通”两个字的文件没有办法在记事本里正常显示的原因。如果多几个字的输入话,
由于记事本检测到不是合格的uft-8编码的字节转而会采用GBK,乱码又不出现。
学习乱码
/search?hl=zh-CN&newwindow=1&q=学习
出现乱码。
编译时的乱码
对于不是平台默认编码的情况下,java源文件在编译时,需要指定源文件的编码,否
则无法正常编译。
1、对于win下默认的GBK编码
C:>
C:>
C:>
:24:警告:编码utf-8的不可映射字符
*????????????????
^
2、对于unicode的默认是utf-16
C:>
:38:非法字符:0
C:>
3、对于utf-8的编码,win下需要删除文件头的二进制编码EFBBBF(因为它是由
Unicode标准的FEFF,为了保证字节序而存在),并不是
C:>
:1:警告:编码GBK的不可映射字符
锘?**
^
:1:非法字符:65533
锘?**
^
1错误
1警告
C:>
:1:非法字符:61371
C:>
:1:非法字符:65279
?/**
^
1错误
注:删除EFBBBF之后的
C:>