服务器JSP编码
pageEncoding
是jsp文件本身的编码,
第一阶段是jsp编译成.java,它会根据pageEncoding的设定读取jsp,(jsp文件的编码,pageEncoding是否一致),结果是由指定的编码方案翻译成统一的UTF-8 JAVA源码(即.java),如果pageEncoding设定错了,或没有设定(在JSP标准的语法中,如果pageEncoding属性存在,那么JSP页面的字符编码方式就由pageEncoding决定,否则就由contentType属性中的charset决定,如果charset也不存在,JSP页面的字符编码方式就采用默认的ISO-8859-1。),出来的就是中文乱码。该参数还有一个功能,就是在JSP中不指定contentType参数,也不使用response.setCharacterEncoding方法时,指定对服务器响应进行重新编码的编码。
contentType
contentType的charset是指服务器发送给客户端时的内容编码
注:
可见,pageEncoding和contentType都可以设置JSP源文件和响应正文中的字符集编码。但也有区别: 设置JSP源文件字符集时,优先级为pageEncoding>contentType。如果都没有设置,默认ISO-8859-1。 设置响应输出的字符集时,优先级为contentType>pageEncoding。如果都没有设置,默认ISO-8859-1。
客户端浏览器编码
URL编码
- 在IE中输入网址http://www.baidu.com/s?wd=春节
查询字符串的编码:
IE:用的是操作系统的编码。
Chrome:UTF-8
FIREFOX:UTF-8
- 在页面链接中:<a href=” http://www.baidu.com/s?wd=春节”>点我</a>
由网页编码决定,都是由Content-Type指定
GET请求
由网页编码决定,都是由Content-Type指定
POST请求
由网页编码决定,都是由Content-Type指定
Jquery ajax请求
在发送请求时,ajax会自动把查询字符串进行UTF-8编码。
$.ajax({
data:[{key=value}]//这样才会自动编码,如果是key=value&。。。自己拼装的则不会编码
});
注:jquery内部会调用jQuery.param方法对参数encode(执行本应浏览器处理的encode)。
编码处理
GET请求
对于GET方式处理编码有两种方法:(服务器为:Tomcat)
- 代码实现,使用硬编码:
new String(request.getParameter(“name”).getBytes(“iso-8859-1”),”客户端编码方式”);
- 服务器下的配置(也就是把硬编码的操作交给了Tomcat了)
在server.xml下配置:
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding='UTF-8'/>
或者:
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" useBodyEncodingForURI='TRUE'/>
- URIEncoding是对所有GET方式的请求的数据进行统一的重新编码。
- useBodyEncodingForURI则是根据响应该请求的页面的request.setCharacterEncoding参数对数据进行的重新编码,不同的页面可以有不同的重新编码的编码,,在默认情况下,该参数为false。
POST请求
request.setCharacterEncoding(arg0); 只针对POST起作用
Javascript编码函数
1. escape()
不能直接用于URL编码,它的真正作用是返回一个字符的Unicode编码值。比如"春节"的返回结果是%u6625%u8282,也就是说在Unicode字符集中,"春"是第6625个(十六进制)字符,"节"是第8282个(十六进制)字符。
它的规则是,escape不编码字符有69个:*,+,-,.,/,@,_,0-9,a-z,A-Z,对其他所有字符进行编码。在\u0000到\u00ff之间的符号被转成%xx的形式,其余符号被转成%uxxxx的形式。对应的解码函数是unescape()。
注:首先,无论网页的原始编码是什么,一旦被Javascript编码,就都变为unicode字符。也就是说,Javascipt函数的输入和输出,默认都是Unicode字符。 其次,escape()不对"+"编码。但是我们知道,网页在提交表单的时候,如果有空格,则会被转化为+字符。服务器处理数据的时候,会把+号处理成空格。所以,使用的时候要小心。
encodeURI()
encodeURI()是Javascript中真正用来对URL编码的函数。
编码后,它输出符号的utf-8形式,并且在每个字节前加上%。 它对应的解码函数是decodeURI()。 需要注意的是,它不对单引号'编码。
encodeURI不编码字符有82个:!,#,$,&,',(,),*,+,,,-,.,/,:,;,=,?,@,_,~,0-9,a-z,A-Z
encodeURIComponent()
与encodeURI()的区别是,它用于对URL的组成部分进行个别编码,而不用于对整个URL进行编码。 encodeURIComponent不编码字符有71个:!, ',(,),*,-,.,_,~,0-9,a-z,A-Z它对应的解码函数是decodeURIComponent()。
有时为什么会使用两次js编码
因为第一次编码,你的参数内容便不带有多字节字符了,成了纯粹的 Ascii 字符串。(这里把编第一次的结果叫成 [STR_ENC1] 好了。[STR_ENC1] 是不带有多字节字符的) 再编一次后,提交,接收时容器自动解一次(容器自动解的这一次,不管是按 GBK 还是 UTF-8 还是 ISO-8859-1 都好,都能够正确的得到 [STR_ENC1]) 然后,再在程序中实现一次 decodeURIComponent (Java中通常使用 java.net.URLDecoder(***, "UTF-8")) 就可以得到想提交的参数的原值。
举个栗子:
String str1 = URLEncoder.encode("程序员","utf-8");//假设为浏览器的第一次编码
String str2 = URLEncoder.encode(str1,"utf-8"); //浏览器第二次编码
String deStr1 = URLDecoder.decode(str2,"gbk");
//服务器进行解码,不论是什么编码都能得到正确的浏览器第一次的编码
String deStr2 = URLDecoder.decode(deStr1,"utf-8");//最后得到正确的字符串
http://www.cnblogs.com/xckxue/p/4202278.html
1.字节和unicode Java内核是unicode的,就连class文件也是,但是很多媒体,包括文件/流的保存方式 是使用字节流的。 因此Java要对这些字节流经行转化。char是unicode的,而byte是字节. Java中byte/char互转的函数在sun.io的包中间有。其中ByteToCharConverter类是中调度, 可以用来告诉你,你用的Convertor。其中两个很常用的静态函数是 public static ByteToCharConverter getDefault() ; public static ByteToCharConverter getConverter(String encoding); 如果你不指定converter,则系统会自动使用当前的Encoding,GB平台上用GBK,EN平台上用 8859_1 我们来就一个简单的例子: "你 "的gb码是:0xC4E3 ,unicode是0x4F60 你用: --encoding= "gb2312 "; --byte b[]={(byte) '\u00c4 ',(byte) '\u00E3 '}; --convertor=ByteToCharConverter.getConverter(encoding); --char [] c=converter.convertAll(b); --for(int i=0;i <c.length;c++) --{ -- System.out.println(Integer.toHexString(c[i])); --} --打印出来是0x4F60 --但是如果使用8859_1的编码,打印出来是 --0x00C4,0x00E3 ----例1 反过来: --encoding= "gb2312 "; char c[]={ '\u4F60 '}; convertor=ByteToCharConverter.getConverter(encoding); --byte [] b=converter.convertAll(c); --for(int i=0;i <b.length;c++) --{ -- System.out.println(Integer.toHexString(b[i])); --} --打印出来是:0xC4,0xE3 ----例2 --如果用8859_1就是0x3F,?号,表示无法转化 -- 很多中文问题就是从这两个最简单的类派生出来的。而却有很多类 不直接支持把Encoding输入,这给我们带来诸多不便。很多程序难得用encoding 了,直接用default的encoding,这就给我们移植带来了很多困难 -- 2.UTF-8 --UTF-8是和Unicode一一对应的,其实现很简单 -- -- 7位的Unicode: 0 _ _ _ _ _ _ _ --11位的Unicode: 1 1 0 _ _ _ _ _ 1 0 _ _ _ _ _ _ --16位的Unicode: 1 1 1 0 _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ --21位的Unicode: 1 1 1 1 0 _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ --大多数情况是只使用到16位以下的Unicode: -- "你 "的gb码是:0xC4E3 ,unicode是0x4F60 --我们还是用上面的例子 -- --例1:0xC4E3的二进制: -- -- 1 1 0 0 0 1 0 0 1 1 1 0 0 0 1 1 -- -- 由于只有两位我们按照两位的编码来排,但是我们发现这行不通, -- -- 因为第7位不是0因此,返回 "? " -- -- -- --例2:0x4F60的二进制: -- -- 0 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0 -- -- 我们用UTF-8补齐,变成: -- -- 11100100 10111101 10100000 -- -- E4--BD-- A0 -- -- 于是返回0xE4,0xBD,0xA0 -- -- 3.String和byte[] --String其实核心是char[],然而要把byte转化成String,必须经过编码。 --String.length()其实就是char数组的长度,如果使用不同的编码,很可 --能会错分,造成散字和乱码。 --例: ----byte [] b={(byte) '\u00c4 ',(byte) '\u00e3 '}; ----String str=new String(b,encoding); ---- ----如果encoding=8859_1,会有两个字,但是encoding=gb2312只有一个字 ---- --这个问题在处理分页是经常发生 4.Reader,Writer/InputStream,OutputStream --Reader和Writer核心是char,InputStream和OutputStream核心是byte。 --但是Reader和Writer的主要目的是要把Char读/写InputStream/OutputStream --一个reader的例子: --文件test.txt只有一个 "你 "字,0xC4,0xE3-- --String encoding=; --InputStreamReader reader=new InputStreamReader( ----new FileInputStream( "text.txt "),encoding); --char []c=new char[10]; --int length=reader.read(c); --for(int i=0;i <c.length;i++) ----System.out.println(c[i]); --如果encoding是gb2312,则只有一个字符,如果encoding=8859_1,则有两个字符 -------- -- -- ---- 2.我们要对Java的编译器有所了解: --javac -encoding 我们常常没有用到ENCODING这个参数。其实Encoding这个参数对于跨平台的操作是很重要的。 如果没有指定Encoding,则按照系统的默认Encoding,gb平台上是gb2312,英文平台上是ISO8859_1。 --Java的编译器实际上是调用sun.tools.javac.Main的类,对文件进行编译,这个类 -- 有compile函数中间有一个encoding的变量,-encoding的参数其实直接传给encoding变量。 编译器就是根据这个变量来读取java文件的,然后把用UTF-8形式编译成class文件。 一个例子: --public void test() --{ ----String str= "你 "; ----FileWriter write=new FileWriter( "test.txt "); ----write.write(str); ----write.close(); --} ----例3 --如果用gb2312编译,你会找到E4 BD A0的字段 -- --如果用8859_1编译, --00C4 00E3的二进制: --00000000 11000100 00000000 11100011-- --因为每个字符都大于7位,因此用11位编码: --11000001 10000100 11000011 10100011 --C1-- 84-- C3-- A3 --你会找到C1 84 C3 A3 -- 但是我们往往忽略掉这个参数,因此这样往往会有跨平台的问题: -- 例3在中文平台上编译,生成ZhClass -- 例3在英文平台上编译,输出EnClass --1. ZhClass在中文平台上执行OK,但是在英文平台上不行 --2. EnClass在英文平台上执行OK,但是在中文平台上不行 原因: --1.在中文平台上编译后,其实str在运行态的char[]是0x4F60, ---- --在中文平台上运行,FileWriter的缺省编码是gb2312,因此 --CharToByteConverter会自动用调用gb2312的converter,把str转化 --成byte输入到FileOutputStream中,于是0xC4,0xE3放进了文件。 --但是如果是在英文平台下,CharToByteConverter的缺省值是8859_1, --FileWriter会自动调用8859_1去转化str,但是他无法解释,因此他会 --输出 "? " ---- --2. 在英文平台上编译后,其实str在运行态的char[]是0x00C4 0x00E3, ---- --在中文平台上运行,中文无法识别,因此会出现?? -- 在英文平台上,0x00C4--> 0xC4,0x00E3-> 0xE3,因此0xC4,0xE3被放进了 --文件 ---- 1.对于JSP正文的解释: --Tomcat首先看一下你的叶面中有没有 " <%@page include的符号。有,则在相同 --地方设定response.setContentType(..);按照encoding的来读,没有他按照8859_1 --读取文件,然后用UTF-8写成.java文件,然后用sun.tools.Main去读取这个文件, --(当然它使用UTF-8去读),然后编译成class文件 --setContentType改变的是out的属性,out变量缺省的encoding是8859_1
2.对Parameter的解释 --很不幸Parameter只有ISO8859_1的解释,这个质料可以在servlet的实现代码中找到。
3.对include的解释 格式的,但是很不幸,由于那个写 "org.apache.jasper.compiler.Parser "的人 在数组JspUtil.ValidAttribute[]忘记加了一个参数:encoding,因此导致不支 持这种方式。你完全可以编译源代码,加上对encoding的支持
总结:
如果你在NT底下,最简单的方法就是欺骗java,不加任何Encoding变量: <html> 你好 <%=request.getParameter( "value ")%> </html>
http://localhost/test/test.jsp?value=你
结果:你好你
但这种方法局限性较大,比如对上传的文章分段,这样的做法是死定的,最好的 解决方案是用这种方案: <%@ page contentType= "text/html;charset=gb2312 " %> <html> 你好 <%=new String(request.getParameter( "value ").getBytes( "8859_1 "), "gb2312 ")%> </html>
Eclipse中如.js,或.properties文件中有中文不能保存的问题的解决方法
Window-》Ppreference-》General -》Content Types -》Text -》JavaScript或Java Properties File,选中它并在Default encoding:把iso8859-1改为utf-8,或gbk,或gb2312,再点击“Update”就可以了。
这里还可以改变其他一些文件的默认编码:如JSP,Java Source File ......
http://www.blogjava.net/luedipiaofeng/articles/307666.html
1: 最基本的乱码问题。
这个乱码问题是最简单的乱码问题。一般新会出现。就是页面编码不一致导致的乱码。
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page contentType="text/html;charset=iso8859-1"%>
<html>
<head>
<title>中文问题</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
</head>
<body>
我是个好人
</body>
三个地方的编码。
第一个地方的编码格式为jsp文件的存储格式。Eclipse会根据这个编码格式保存文件。并编译jsp文件,包括里面的汉字。
第 二处编码为解码格式。因为存为UTF-8的文件被解码为iso8859-1,这样 如有中文肯定出乱码。也就是必须一致。而第二处所在的这一行,可以没有。缺省也是使用iso8859-1的编码格式。所以如果没有这一行的话,“我是个好人”也会出现乱码。必须一致才可以。
第三处编码为控制浏览器的解码方式。如果前面的解码都一致并且无误的话,这个编码格式没有关系。有的网页出现乱码,就是因为浏览器不能确定使用哪种编码格式。因为页面有时候会嵌入页面,导致浏览器混淆了编码格式。出现了乱码。
2:表单使用Post方式提交后接收到的乱码问题
这个问题也是一个常见的问题。这个乱码也是tomcat的内部编码格式iso8859-1在捣乱,也就是说post提交时,如果没有设置提交的编码格式,则会以iso8859-1方式进行提交,(tomcat默认编码:ISO8859-1)接受的jsp却以utf-8的方式接受。导致乱码。既然这样的原因,下面有几种解决方式,并比较。
A :接受参数时进行编码转换
String str = new String(request.getParameter("something").getBytes("ISO-8859-1"),"utf-8") ;
这样的话,每一个参数都必须这样进行转码。很麻烦。但确实可以拿到汉字。
B :在请求页面上开始处,执行请求的编码代码, request.setCharacterEncoding("UTF-8"),把提交内容的字符集设为UTF-8。这样的话,接受此参数的页面就不必在 转码了。直接使用String str request.getParamet("something");即可得到汉字参数。但每页都需要执行这句话。这个方法也就对post提交的有效果,对于get提交和上传文件时的enctype="multipart/form-data"是无效的。稍后下面单独对这个两个的乱码情况再进行说明。
C :为了避免每页都要写request.setCharacterEncoding("UTF-8"),建议使用过滤器对所有jsp进行编码处理。
3 :表单get提交方式的乱码处理方式
如果使用get方式提交中文,接受参数的页面也会出现乱码,这个乱码的原因也是tomcat的内部编码格式iso8859-1导致。Tomcat会以get的缺省编码方式iso8859-1对汉字进行编码,编码后追加到url,导致接受页面得到的参数为乱码。
解决办法:
A 使用上例中的第一种方式,对接受到的字符进行解码,再转码。
B Get走的是url提交,而在进入url之前已经进行了iso8859-1的编码处理。要想影响这个编码则需要在
server.xml 的Connector节点增加useBodyEncodingForURI="true" 属性配置,即可控制tomcat对get方式的汉字编码方式,上面这个属性控制get提交也是用 request.setCharacterEncoding("UTF-8")所设置的编码格式进行编码。所以自动编码为utf-8,接受页面正常接受就 可以了。但我认为真正的编码过程是,tomcat又要根据
<Connector port="8080"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
debug="0" connectionTimeout="20000" useBodyEncodingForURI="true"
disableUploadTimeout="true"
URIEncoding=”UTF-8”/>里面所设置的URIEncoding=”UTF-8”再进行一次编码,
但是由于已经编码为utf-8,再编码也不会有变化了。
如果是从url获取编码,接受页面则是根据URIEncoding=”UTF-8”来进行解码的。
1. (客户端乱码)IE中显示乱码
1).<%@page pageEncoding="utf-8"%>----------------->指定javac.exe用什么方式去读jsp文件
2).注意:jsp文件另存为的时候,要选择utf-8格式保存.===>和第一步一致
3).<%@page contentType="text/html;charset=utf-8"%>------>指定reponse返回流用什么编码
4).注意: IE中-->查看-->编码--->会自动选择utf-8===>和第三步一致
注意:html的meta中的<meta http-equiv="content-Type" content="text/html; charset=utf-8">是不起任何作用的。它只在IE直接打开本地的html文件时有用,在这种情况下,由它来告诉IE,到底使用哪种编码方式去读本地的html文件。
(可能不对,因为IE还没有读html怎么知道该文件中含有这个信息呢,如果已经读了,那还要该信息干什么。)
2.(服务器端乱码)在*.java中request.getParameter("username");是乱码
html中的form含有中文时,form提交到服务器端的流的编码方式----与“IE中-->查看-->编码--->会自动选择utf-8”是一致的。所以,在java中,在取参数之前,用:request.setCharacterEncoding("UTF-8");