先理解一下java里的编码
假设有两个字符String str = “OX”在jvm中的byte表现为 AB CD 13 57(这里是假设)。那么执行str.getBytes("")后会变成什么样呢
字符编码 O X
UTF-16(JVM) AB CD 13 57
getBytes("SJIS") 1A 2B 3C 48
getBytes("UTF-8") 12 56 78 90 34
getBytes("MS932") 1A 2B 3C 4D
getBytes("ISO-8859-1") CD 57
getBytes('UTF-16') AB CD 13 57
解析:String.getBytes
在这个时候,str已经在jvm中存在,并且以UTF-16编码存在,这个时候的编码为 AB CD 13 57 ------即在jvm的内存中存在这样的byte表示这str
执行getBytes("SJIS") :在jvm底层有有UTF-16和SJIS的对应关系,那么查询这个对应关系可以知道AB CD对应着1A 2B、13 57对应着3C 48。因此getBytes("SJIS") 获得的编码是1A 2B 3C 48。其他类似
这里有一个是特殊的:getBytes("ISO-8859-1") 执行的是去高位,即AB CD--〉CD 13 57--〉57.所以getBytes("ISO-8859-1")后结果为 CD 57
解析new String(byte[],charsetName)
假设 byte[] b = "OX".getBytes("SJIS") ,执行String str2 = new String(b,“SJIS”) 那么str2将可以正确显示,因为b里存的是SJIS的编码,那么使用SJIS去解析是可以正确解析
new String(byte[],charsetName)的作用是使用charsetName去解析byte[]。如果直接new String(byte[]),那么jvm将使用系统的charsetName。这是可能导致乱码
这里有一个特殊 假设 byte[] b1 = "OX".getBytes("ISO-8859-1") ,执行String str2 = new String(b,“ISO-8859-1”) 那么str2的结果肯定是乱码,他的字节是
00 CD 00 57 因为"OX".getBytes("ISO-8859-1") 是去高位操作,new String(b,“ISO-8859-1”) 是在高位上加00操作
浏览器传输内容机制
浏览器在传输时内容,会先取得页面的字节内容(这是字节内容是什么编码的是根据文件的编码来决定),然后用new String(b,“ISO-8859-1”) 给高位加00,然后传输给服务器,服务器应该需要new String(req.getParameter("test55").getBytes("ISO-8859-1"),charsetName)来解析获得的内容。当然也可以设置req.setCharacterEncoding("UTF-8");来给request一个提示,传送过来的是UTF-8.那么在getParamer时自动解析
jsp乱码分几种
1.编辑jsp是乱码,说明文件编码没有设置正确。比如你升级某项目,拿来的是前辈些的jsp文件,根本不知道他原来的文件编码是什么,这时候怎么办呢,我也正在调查中
2.编辑jsp时是正确显示,但是用浏览器打开时发现乱码,是因为jsp页面的contentType编码和jsp文件的编码不一致。
如果页面的内容是通过resp.getWrite().println()打出来的,那么要设置一下resp.setContentType("text/html; charset=UTF-8")。但是这里该设置成什么编码呢,这要看你希望浏览器用什么编码来解析你的内容(这里其实设置什么都可以,只要你的浏览器支持该编码,当然也需要能正确解析的编码,比如“そうです”设置成gb2312编码,当然是乱码了,这个时候设置成utf-8或者SJIS或者MS932)
3.jsp提交到后台出现乱码。因为传输时会执行new String(b,“ISO-8859-1”) ,因吃后台java需要new String(req.getParameter("test55").getBytes("ISO-8859-1"),charsetName)来转换。charsetName必须是jsp的编码