字符集与编码

来源:互联网 发布:openwrt 网络唤醒 编辑:程序博客网 时间:2024/06/06 09:08

字符集和编码一直弄不懂两者之间的关系,查了很多资料,看了一些博客,做个总结。

字符集和编码

  • 什么是字符集:

    是一个系统支持的所有抽象字符的集合。字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。

  • 什么是编码

    是一套法则,使用该法则能够对自然语言的字符的一个集合(如字母表或音节表),与其他东西的一个集合(如号码或电脉冲)进行配对。即在符号集合与数字系统之间建立对应关系,它是信息处理的一项基本技术。通常人们用符号集合(一般情况下就是文字)来表达信息。而以计算机为基础的信息处理系统则是利用元件(硬件)不同状态的组合来存储和处理信息的。元件不同状态的组合能代表数字系统的数字,因此字符编码就是将符号转换为计算机可以接受的数字系统的数,称为数字代码。

为什么要有编码?

首先大家要明确的知道在计算机里所有的数据都是以字节的形式存储和处理的。我们需要字节来表示计算机里的信息,但是这些字节本身又是没有任何意义的。我们需要对这些字节赋予实际的意义,制定各种编码标准。

常用的字符集有:

  • ASCII字符集
  • GB2312字符集
  • GBK字符集
  • Unicode字符集

常用的编码方式

  • ASCII
  • ISO8859-1
  • GB2312
  • GBK
  • UTF-8。

ASCII字符集&编码

编码范围0x00-0x7F,ASCII字符集包括英文字母、阿拉伯数字和标点符号等字符。是当时美国制定出来的一套编码系统,使用7位二进制来表示西文字符,0-31以及127为控制字符或通信用字符,其余为可显示出来的字符。在标准的ASCII中最高位b7作为奇偶校验位。后面128个则称为扩展ASCII码,以满足当时不同地方特殊符号的需求。

ISO8859-1字符集&编码

属于单字节编码,使用8位二进制存储,向下兼容ASCII,不能表示中文。其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致。

gb2312字符集&编码

基于区位码寻址方式,对所收汉字进行了“分区”处理,每区含有94个汉字/符号。
01-09区为特殊符号
16-55区为一级汉字,按拼音排序
56-87区为二级汉字,按部首/笔画排序。
10–15区及88–94区则未有编码。但在附录3,则在第10区推荐作为 GB 1988–80 中的94个图形字符区域(即第3区字符之半形版本)。
每个汉字及符号用两个字节来表示,第一个字节称为“高字节”,第二个字节称为“低字节”。
“高字节”使用了0xA1-0xF7(把01-87区号加上0xA0),“低字节”使用0xA1-0xFE(把01-94加上0xA0)。占用的码位是72*94=6768,其中有5个空位是D7FA-D7FE。

GBK字符集&编码

有一字节和双字节编码,00-7F范围是第一个字节,和ASCII保持一致。
之后的双字节中,前一个字节是双字节的第一位,总体上说第一字节的范围是81-FE,第二字节的一部分领域字40-7E,其他领域在80-FE。虽然gb2312囊括了大部分汉字,但还是有一些像繁体字和符号就没有编入进来,于是再次进行扩展,便有gbk。

Unicode字符集&编码

是一个字符集,包含了世界上所有的字符。中文文字在Unicode的编码范围是:u+4e00-u+9fa5。它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。

UTF-8字符集&编码

UTF-8是在互联网上使用最广的一种Unicode的实现方式。UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,对英文字符使用一个字节存储,中文字符使用三个字节存储。

UTF-8的编码规则:

  • 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的Unicode码。因此对于英文字符,UTF-8和ASCII码是一样的。
  • 对于n(n>1)字节的符号,第一个字节的前n位都设为1,第n+1为设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部设为这个符号的Unicode码。

unicode和UTF-8的转换规则

这里写图片描述

比如“优”字,Unicode编码为4F18,属于0800-FFFF的范畴内,则它的UTF-8编码使用三字节的的模板。
将4F18转换成二进制为:0100 1111 0001 1000;按照三字节的模板进行UTF-8编码转换成的二进制位:
1110-0100 10-1111100 10-011000。对应的十六进制为E4BC98,这就是“优”字在UTF-8的编码。

为什么会出现乱码?

原因:编码和解码时用了不同或者不兼容的字符集。比如一个用UTF-8编码后的字符,拿去用GBK解码,由于两个字符集的字符库不一样,同一个汉字在两个字符表的位置也不一样,最终就会出现乱码。看下面一个‘栗子’:假设使用UTF-8编码存储“优护家”三个汉字,会有如下的转换:
这里写图片描述

那么使用GBK进行解码会出现什么结果?

由于GBK是双字节存储字符,“优护家”经过UTF-8编码形成的编码值将被拆
分为:E4BC,98E6,8AA4,E5AE,B6。
这些十六进制数值对应的汉字与“优护家”三个汉字完全不同,而且字符的个数
还发生了变化。这就产生了乱码。
“优护家”经过GBK编码存储转换十六进制是:
这里写图片描述

从这里可以看出,在GBK中,能真正表示“优护家”这三个字的十六进制编码是D3C5BBA4BCD2.

tomcat服务器以及web应用涉及到的乱码问题及解决方案

客户端与Tomcat交互过程的encode和decode图示

这里写图片描述

tomcat应用默认的字符集编码为ISO8859-1,此字符集不支持中文,所以在web应用中涉及到了中文字符就会出现乱码。以下列出几种在web应用中出现中文乱码的情况:

  • jsp页面响应乱码

原因 : jsp页面默认的字符集是ISO8859-1,所以页面包含中文字符时,就会
出现乱码。
解决 : 设置pageEncoding属性值为一个支持中文字符的字符集

  • servlet响应乱码

原因 : 没有设置响应编码,Response默认使用ISO8859-1将响应数据进行编
码。
解决 : response.setCharacterEncoding(“”)方法设置一个支持中文的编码方
式。

  • 服务器端获取get请求的数据乱码

原因 : 当浏览器端以GET请求的方式向服务器端发送数据,浏览器先将数据
按照页面的编码方式进行编码成byte字节进行传输,服务器端接收当数据时,
tomcat会根据URIEncoding将数据进行解码,如果没有设置URIEncoding的
话,tomcat会默认使用ISO8859-1对数据进行解码。
解决 : 在server.xml设置URIEncoding为支持中文字符的编码方式。

  • 服务器端获取POST请求数据乱码

原因 : 当浏览器端以POST请求的方式向服务器端发送数据,浏览器先将数据
按照页面的编码方式进行编码成byte字节进行传输,服务器端接收当数据时,
tomcat服务器会获取到请求头信息里的编码方式,tomcat根据请求头里的编
码方式将数据进行解码。如果POST请求在请求头信息里没有设置编码方式,
tomcat默认使用ISO8859-1进行解码。
解决 : 设置请求头的编码方式为支持中文字符的编码方式。