字符编码方式及大端小端

参考资料:

http://www.cnblogs.com/zhouyuqin/p/4688459.html

http://pcedu.pconline.com.cn/empolder/gj/other/0505/616631_1.html

 

常见的编码格式总结:

ASCLL:单字节
ISO-8859-1(latin-1):单字节,与ASCLL的不同在于使用了最高位参与编码
GB2312:双字节,简体汉字
GBK:双字节,对GB2312的扩展,完全兼容GB2312,不兼容BIG5
GB18030:单字节、双字节或四字节,与GB2312兼容
BIG5:双字节,繁体汉字。BIG5与GB2312没有关系,不兼容
UCS-2:双字节编码,BOM机制标记大端小端(FE FF或FF FE开头)
UCS-4:四字节编码,BOM机制标记大端小端(FE FF或FF FE开头)
UTF-16:双字节(基本平面)或四字节(辅助平面)编码
UTF-8:1-4字节变长编码,汉字3字节,BOM机制标记编码方式(EF BB BF开头)而不是标记大端小端。

1、ASCII码

单字节编码,总共128个,用1个字符的低7位表示,0~31是控制字符,如换行、回车、删除等。32~126是打印字符,可以通过键盘输入并且表示出来
 

2、ISO-8859-1(即Latin1)

ISO组织在ASCII的基础上又制定了一系列标准来扩展ASCII编码,他们是ISO-8859-1和ISO-8859-15。其中前者涵盖了大多数西欧语言字符,所以运用得比较广泛。
ISO-8859-1仍然是单字节编码,它向下兼容ASCLL(ASCII编码是一个7位的容器,ISO-8859-1编码是一个8位的容器),总共能表示256个字符,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号。.
因为ISO-8859-1是单字节的,所以很多中文字符(两个字节)在编码时用ISO-8859-1表示时,因超出表示范围,所以出现??很多情况是将中文字符用ISO-8859-1表示。我们称之为“黑洞”(它会将不认识的字符吸收掉)。
由于现在大部分基础的Java框架或系统默认的字符集编码都是ISO-8859-1,所以很容易出现乱码问题。
 

3、GB2312

GB2312是双字节编码,总的编码范围是A1-F7,其中A1-A9是符号区,总共有682个符号,B0-F7是汉字区,包含6763个汉字。
 

4、GBK

GBK是双字节编码,全称是 汉字内码扩展规范,是中国国家技术监督局开发出来扩展GB2312,并加入了更多的汉字,它的编码范围是8140~FEFE,能表示21003个汉字。它与GB2312是兼容的。
 

5、GB18030

Gb18030全称是 信息技术中文编码字符集,是我国的强制标准,它可能是单字节的、双字节或者是四字节编码。它的编码与GB2312编码兼容。
  

6、BIG5

BIG5是双字节编码,是繁体中文字符集编码标准,使用两个字节来表示一个字符。高位字节使用了0x81-0xFE,低位字节使用了0x40-0x7E,及0xA1-0xFE。该编码共收录13060个中文字,其中有二字为重复编码,即“兀、兀”(A461及C94A)和“嗀、嗀”(DCD1及DDFC)。点击这里,查看BIG5编码。

注意,BIG5编码  与  GBK编码、GB2312等没有什么关系,与它们不兼容。

 

 
 
Unicode是一种字符集,学名是"Universal Multiple-Octet Coded Character Set",简称为UCS。UCS可以看作是"Unicode Character Set"的缩写。
Unicode的目标是将世界上所有的字符都纳入其中,每个字符对应一个独一无二的数字。具体的符号对应表,可以查询unicode.org,或者专门的汉字对应表中文的范围是4E00-9FA5,大概两万多个
有两个独立的, 创立单一字符集的尝试. 一个是国际标准化组织(ISO)的 ISO 10646 项目, 另一个是由多语言软件制造商组成的协会组织的 Unicode 项目. 后来它们合并双方的工作成果, 并为创立一个单一编码表而协同工作. 两个项目仍都存在并独立地公布各自的标准, 但 Unicode 协会和 ISO/IEC JTC1/SC2 都同意保持 Unicode 和 ISO 10646 标准的码表兼容, 并紧密地共同调整任何未来的扩展。
Unicode只是一个符号集,只规定的字符所对应的码点,并没有指定如何存储,如何进行存储出现了不同的编码方案,关于Unicode编码方案主要有两条主线:UCS和UTF。UTF主线由Unicode Consortium进行维护管理,UCS主线由ISO/IEC进行维护管理。

7、UCS-2

Unicode字符集的一种编码实现,用2个字节编码。

UCS-2是定长字节的,固定使用2个字节进行编码,从0000(十六进制)- FFFF(十六进制)的码位范围,对应第一个Unicode平面。

采用BOM(Byte Order Mark)机制,该机制作用如下:1. 确定字节流采用的是大端序还是小端序(如果一个文本文件的头两个字节是FE FF,就表示该文件采用大端方式;如果头两个字节是FF FE,就表示该文件采用小端方式。)。2. 确定字节流的Unicode编码方案。

8、UCS-4

Unicode字符集的一种编码实现,用4个字节编码。

UCS-4是定长字节的,固定使用4个字节进行编码。也采用了BOM机制。

9、UTF-16

UTF-16是Unicode字符集的一种编码实现,其基本平面用2个字节编码,辅助平面用4个字节编码。
Java内部以UTF-16作为内存中字符存储格式。
 

10、UTF-8

UTF-8是Unicode字符集的另一种编码实现,以8位为单位对UCS进行编码。
UTF-8采用变长的方法,克服了UTF-16中定长的浪费资源的缺点。每个编码区域都有自己不用的字码长度,不同类型的字符可以由1~6个字节组成。
UTF-8对单字节范围内的字符仍然用1个字节表示,对汉字采用3个字节表示。

UTF-8的编码规则很简单,只有二条:

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

2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

下表总结了编码规则,字母x表示可用编码的位。

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

根据上表,解读UTF-8编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。

 已知"严"的unicode是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800-0000 FFFF),因此"严"的UTF-8编码需要三个字节,即格式是"1110xxxx 10xxxxxx 10xxxxxx"。然后,从"严"的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,"严"的UTF-8编码是"11100100 10111000 10100101",转换成十六进制就是E4B8A5。
 UTF-8以字节为编码单元,没有字节序的问题,不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。BOM的UTF-8编码是EF BB BF。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了(这是微软的做法)。微软在 UTF-8 中使用了 BOM ,因为这样可以把 UTF-8 和 ASCII 等编码明确区分开,但这样的文件在 Windows 之外的操作系统里会带来问题。
 
 
 
上述几种编码格式的比较:
GBK能处理所有的汉字字符,所以将GB2312和GBK进行比较时,应该选择GBK。
UTF-8与UTF-16都是处理Unicode编码,尽管他们的编码格式不相同,但相对来说,UTF-16的编码效率较高,从字符到字节的转换更简单,进行字符串操作也更好,适合磁盘和内存之间使用,所以Java的内存编码采用UTF-16来编码。但是在网络传输的时候,应使用UTF-8,因为网络传输比较容易损坏字节流,而UTF-8对ASCII字符采用了单字节编码,另外单个字节损坏不会影响到后面的其他字符,在编码效率中介于GBK和UTF-16之间,所以,UTF-8在编码效率和编码安全性方面都做了平衡,是理想的中文编码方式。
 gbk与unicode之间的转换是通过gbkunicode映射表。Utf-8与unicode之间的转换是通过转换规则公式所以说,unicode是核心中介。Gbk要转换成utf-8的话,先转成unicode。然后unicode再转换成utf-8;反之亦然。 

 

11、大端小端

Windows下用记事本打开文本文件并另存为时,有四种编码方式可以选择:ANSI,Unicode,Unicode big endian 和 UTF-8。
  1. ANSI是默认编码方式,对于英文文件是ASCII编码,对于简体中文文件是GB2312编码(只针对Windows简体中文版,如果是繁体中文版会采用Big5码
  2. Unicode编码指的是UCS-2编码方式(微软软件的习惯),即直接用两个字节存入字符的Unicode码。这个选项用的little endian格式。
  3. Unicode big endian编码与上一个选项相对应。
  4. UTF-8编码。

 

另,关于大端小端:

[  大端小端取决于CPU架构,powerpc,aix、SPARC等是大端;x86架构处理器(Intel、AMD,PC)、arm架构处理器(arm,手机)是小端  ]

采用大小模式对数据进行存放的主要区别在于在存放的字节顺序,若数字的高位在内存中的低地址则是大端(即数字在内存中的二进制形式的第一字节是数字的高位),否则是小端。

采用小端方式进行数据存放利于计算机处理,因此计算机的内部处理较多用小端字节序。比如整数的加法和乘法、数的比较、奇偶性校验等,因为从个位比起即可而此时不用全读进来;另例是C语言的大整型向小整型的强转,直接截断实现下若是用小端存储则指针不用变而大端要变。

采用大端方式进行数据存放符合人类的正常思维,除了计算机的内部处理,其他的场合几乎都是大端字节序,比如网络传输和文件储存。

到目前为止,采用大端或者小端进行数据存放,其孰优孰劣也没有定论。

 

那么:对于Unicode字符集的编码(UCS-2、UTF-16、UTF-32等),计算机怎么知道某一个文件到底采用哪一种方式编码

Unicode规范中定义,每一个文件的最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做"零宽度非换行空格"(ZERO WIDTH NO-BREAK SPACE),用FEFF表示。这正好是两个字节,而且FF比FE大1。

如果一个文本文件的头两个字节是FE FF,就表示该文件采用大端方式;如果头两个字节是FF FE,就表示该文件采用小端方式。

另外,UTF-8是不需要BOM的因为其没有字节序的问题,编码自身就包含了字节指示信息,但微软在 UTF-8 中使用了 BOM ,因为这样可以把 UTF-8 和 ASCII 等编码明确区分开,但这样的文件在 Windows 之外的操作系统里会带来问题。

 

更多见 彻底理解字符编码

 

posted @ 2015-07-30 13:00  March On  阅读(3004)  评论(0编辑  收藏  举报
top last
Welcome user from
(since 2020.6.1)