电脑只能处理0100110这样的二进制数字,字符是日常生活中我们使用的符号,为了使电脑能够存储、传输和展示字符,我们需要把字符转换为0100101这样的二进制码,这就是编码。
相反,把0100110这样的二进制码转换为字符的过程就是解码。
至于把哪个字符映射到哪个二进制串上,是由国家(国家标准)、国际组织(国际标准)等来决定的。
一般不用二进制串来表示字符的编码(看和阅读都很困难),而是用十六进制的串来表示某个字符的编码。因此,字符<-->十六进制串,之间的映射的集合就是我们所说的字符集了。
我们经常见到的字符集有:Unicode,UTF-8,GBK,GB2312,GB18030,Big-5,ISO-8859-1(又叫Latin-1)
-
Unicode,UTF-8能够支持目前世界上所有语言文字的字符
-
GB2312是旧的国家标准,不支持繁体汉字
-
GBK不是国家标准,但支持繁体汉字
-
GB18030是新的国家标准,也支持繁体汉字
-
Big-5,能支持繁体汉字
-
ISO-8859-1不支持汉字,英美等拉丁语系的国家常用这个编码
中国两个字,用不同的编码方式进行编码,得到的结果也不相同 :
-
Unicode - FE, FF, 4E, 2D, 56, FD
-
UTF-8 - E4, B8, AD, E5, 9B, BD
-
GB18030 - D6, D0, B9, FA
-
ISO-8859-1 - 3F, 3F
关于Unicode:
用Unicode编码后的“中国”,其编码的前面有FE,FF两个额外的字节,这两个字节称为BOM(Byte Order Mark)。“中”这个汉字,它的Unicode编码是4E,2D,那么在传输的过程中,是把4E放在前面,还是把2D放在前面呢?这有BOM来决定,如果BOm是FEFF(称为Big Endian),表示4E在前面,如果BOM是FFFE(称为Little Endian),表示2D在前
也就是,如果你的文件编码是Unicode(也可以叫做UTF-16),那么文件开头的字节就是FEFF(以这种方式开头的编码叫UTF-16BE)或FEFF(以这种方式开头的叫UTF-16LE)。UTF-16BE、UTF-16、Unicode是一样的。
关于UTF-8:
UTF-8编码的文件,其文件也有一段标识:EF BB BF
其他编码:
其他编码的文件。其文件头没有什么标识,关于ISO-8859-1对于“中国”的编码是3F,3F,两个相同,是应为它的字符集中根本就没有“中国”这两个字,所以用3F代替。
Java中的编码和解码问题:
JAVA可以把字符存储在内存中(即也是以01101110的形式存储在内存中)。Java在内存中存储的编码格式是Unicode。不过Java的class文件是以UTF-8的方式来编码的。Java虚拟机读取class文件后,通过UTF-8编码把文件读入内存,再转换为UTF-16编码.因此,如果语句是new String(byte[], "GB18030"),就是把字节流(以GB18030编码的)转换为Unicode编码的字节流存入内存中。
如果想把一个字节流转换为字符流,就需要知道该字节流是以什么方式来编码的,然后根据他的编码方式来解码就可以了。 开源工具:chardet,可以用来猜测某一段字节流是用什么编码的。
如果我们拿到的一个字符串,输出时发现是一串乱码,那么是否可以通过某种技术手段来解决这个乱码问题呢?答案是:不一定。
因为,首先该字符串一定是先根据某个字符集将一个字节流进行解码而得到的。那么:
-
如果它是按照ISO-8859-1字符集对字节流进行解码而得到的字符串,恭喜你,你可以通过某种手段,把手中的乱码重新转换为正确的字符串。方法就是:先getBytes("ISO-8859-1 "),得到一个字节流,再用new String(Byte[], "正确的字符集")转换为正确的字符串即可。
-
如果它不是按照ISO-8859-1 字符集来解码的,那很大可能就不能再转换为正确的字符串了。
通过Get方法想后台递交请求:
向服务器递交的请求中,字符也是需要编码之后传输的。浏览器将自动对URL地址中的汉字进行编码之后传输。如果你直接在URL地址中输入汉字,浏览器会根据当前字符的默认字符集进行编码(中文操作系统是GB2312)再传输到服务器;如果是在某个页面中点击的附带中文的连接,那么浏览器会根据这个页面所使用的字符集对汉字进行编码之后,传输到服务器。
为了避免每次的编码麻烦,我们可以直接在Tomcat中修改他对URL编码的默认解码字符集。就是修改server.xml文件中的下面的语句,加上URIEncoding="GB18030"的配置:
<Connector port="8080" protocol="HTTP/1.1"
connection Timeout="20000"
redirectPort="8443" URIEncoding="GB18030"/>
通过Post方法向后台递交请求:
浏览器将按照表单所在页面所使用的字符集对数据进行编码之后传输!在Tomcat中配置URIEncoding只对Get请求有效;对于Post请求,则必须在调用request.getParameter("XXX")之前,调用request.setCharacterEncoding("GB18030");
reponse编码:
在调用response.getWrite()之前,调用response.setCharacterEncoding("GB18030") ;或者在执行response.setContentType("text/html;charset=GB18030");