技术文章 | 计算机字符编码详解与汇总

来源:互联网 发布:windows sdk 版本8.1 编辑:程序博客网 时间:2024/06/05 08:40

前言

       计算机中的数据是以二进制格式表示的(其中8位二进制称为一个字节,比如00100101就是一个字节。通常为了更方便的表示二进制数据,也可以转换成16进制表示出来,比如00100101就可以用0x25来表示)。把所有字符转换成二进制数据的规则就是字符编码。字符编码的方式很多,本文对每一种字符编码做尽可能详细的讲解。

       本文中红色字体或加粗字体是需要重点理解或者记忆的。

1. ASCII

       ASCII是美国国家标准定制的一套基于拉丁字母的电脑编码系统,可表示数字、字母等字符符号。

       一个ASCII码在计算机中由一个字节存储,因此它最多可表示256个符号(一个字节为8位,28次方等于256),实事上,标准的ASCII编码时只用到了低7(最高位统一为0,或者为奇偶校验位),故ASCII码可表示的数据一共只有128个(27次方)。这128个字符中,其中95个为可显示字符(可打印字符,比如数字、字母、标点符号),还有33个如比如“换行”之类的控制字符(控制字符主要是用来操控已经处理过的文字)。

       对于ASCII具体哪个编码表示哪个符号,大家可以去查阅ASCII编码码表,并具最好能记住数字符、字母、回车换行等常用字符对应的ASCII编码,至少记住它的十进制编码。

常用字符对应的ASCII编码:

回车,ASCII13(十进制,下同)
换行,ASCII10
空格,ASCII32

数字09ASCII依次是4857

大写字母AZASCII依次是6590

小写字母azASCII依次是97122

大小规则总结:

1)数字0~9比字母要小。如"7"<"F"

2)数字0比数字9要小,并按09顺序递增。如"3"<"8"

3)字母A比字母Z要小,并按AZ顺序递增。如"A"<"Z"

4)同个字母的大写字母比小写字母要小。如"A"<"a"

 

2. iso8859-1

       iso8859-1通常叫做Latin-1它和ascii编码相似,都属于单字节编码,不同于ASCII的是,每个字节中的最高位也参与了编码(如果最高位为0,它的意义同ASCII)。正因为如此,iso8859-1最多能表示的字符范围是0-255,应用于英文系列。很明显,iso8859-1编码表示的字符范围很窄,无法编码中文字符。尽管如此,我们可以先把中文字符按照其它的编码方式编码成二进制数据,然后将编码后的结果再逐字节逐字节的用iso8859-1解码。也就是说,中文字符,它没有iso8859-1编码,但可以在用其它编码方式编码后的基础上再用iso8859-1编码来表示。举个栗子,虽然“中文”的“中”这个字不存在iso8859-1编码,可以先把它按gb2312编码方式编码为"d6d0"这个二字节的编码(16进制),然后将它拆开为两个字节("d6" "d0"),每个字节都可以看作是一个iso8859-1码。

iso8859-1编码在网络传输中的利用:

       iso8859-1由于是单字节编码,和计算机最基础的表示单位一致,因此在很多网络传输协议上,默认使用iso8859-1编码。网络上传输的数据都是二进制的,服务器从网络io流中收到这些数据后,默认把每个字节的数据按iso8859-1编码来处理。

       实事上,通过网络流传输中文时,客户端可以先把中文字符按照其它的编码方式(比如GBKUTF-8)转换成字节数据发送到服务器,服务器收到后在不指定编码方式的情况下默认会逐个逐个字节的按照iso8859-1编码方式来解码。

       写点题外话,对于java web程序员来说,有时候可以在servlet代码中看到类似于String str = new String(restr.getBytes("iso8859-1"),"utf-8");的转换代码,它的意思就是先把字符串restr通过restr.getBytes("iso8859-1")编码为字节数组(restr是请求参数被按照iso8859-1方式解码后的结果。如果请求参数为中文,因为iso8859-1编码无法直接解码中文,会导致解码后的restr为乱码),然后再按照utf-8的编码方式重新转换为一个新的字符串。

       当然,在java web中也可以用request.setCharacterEncoding("utf-8");方法,直接告诉服务器按照指定的utf-8方式编码。但值得一提的是在执行setCharacterEncoding()之前,不能执行任何getParameter(),而且,该指定只对POST方法有效,对GET方法无效。原因是在执行第一个getParameter()的时候,java将会按照编码分析所有的提交内容,而后续的getParameter()不再进行分析,所以setCharacterEncoding()无效。而对于GET方法提交表单是,提交的内容在URL中,一开始就已经按照编码分析所有的提交内容,setCharacterEncoding()自然就无效。多说一句,为了避免总是要写setCharacterEncoding("utf-8"),通常会在web.xml配置文件中配置一个最上层的字符编码过滤器。

 

3. GB2312

       无论是ascii码还是iso8859-1码,都无法直接编码中文,于是有了GB2312码。GB2312 是对 ASCII 的中文扩展,考虑到每个ASCII码只用了一个字节的底7位(高位为0),所以每个的ASCII码都小于或等于12701111111)。于是规定:一个小于127的字符的意义与原来相同(为了兼容ASCII码),但两个大于127的字符连在一起时,就表示一个汉字,而且这两个字节中,前面的一个字节(他称之为高字节)从0xA1用到0xF7,后面一个字节(低字节)从0xA10xFE,这样我们可以组合出大约7000多个简体汉字,这就是GB2312编码。

       这样,计算机在解码时,可以逐字节逐字节的判断它的是否小于127,如果小于或等于127,就按ASCII直接解码,如果大于127,就再往后多读取一个字节,如果后面那个字节也大于127,就把这两个字节连起来再通过查找GB2312编码码表来解码成一个中文字符。由此可见,GB2312码是一种变长的编码方式,英文占一个字节(而且小于127),中文占两个字节(都是大于127的字节),而且兼容ASCII

查看全文

原创粉丝点击