编者说的话:为什么说乱码是中国程序员无法避免的话题呢?这个首先要从编码机制上说起,大家都是中文和英文的编码格式不是一样,解码也是不一样的!如果中国的程序员不会遇到乱码,那么只有使用汉语编程。汉语编程是怎么回事我也不大清楚,应该是前年吧,我一朋友给我介绍汉语编程,怎么不错不错?当时因为学习忙没去关注这个,等我闲了,那个朋友不弄这个,问他他也不说不大清楚,最后自己对这个学习也不了了之了。
今天我写这个不是讲解中英文之间的差距,解码等,我是将我在这几年工作遇到各种各样的乱码的解决方法,总结一样,也希望大家能把自己晕倒解决乱码的方法都说出来,咱们弄一个解决乱码的“葵花宝典”。
对于Java由于默认的编码方式是 UNICODE,所以用中文也易出问题,常见的解决是
- String s2 = new String(s1.getBytes("ISO-8859-1"),"UTF-8");
1、utf8解决JSP中文乱码问题:
一般说来在每个页面的开始处,加入:
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <% request.setCharacterEncoding("UTF-8"); %>
charset=UTF-8 的作用是指定JSP向客户端输出的编码方式为"UTF-8".
pageEncoding="UTF-8" 为了让JSP引擎能正确地解码含有中文字符的JSP页面,这在LINUX中很有效.
request.setCharacterEncoding("UTF-8"); 是对请求进行了中文编码.
有时,这样仍不能解决问题,还需要这样处理一下:
- String msg = request.getParameter("message");
- String str=new String(msg.getBytes("ISO-8859-1"),"UTF-8");
- out.println(str);
2、Tomcat 5.5 中文乱码:
(1).只要把%TOMCAT安装目录%/webapps/servlets-examples/WEB-INF/classes/filters/SetCharacterEncodingFilter.class文件拷到你的webapp目录/filters下,如果没有filters目录,就创建一个。
(2).在你的web.xml里加入如下几行:
- <filter>
- <filter-name>Set Character Encoding</filter-name>
- <filter-class>filters.SetCharacterEncodingFilter</filter-class>
- <init-param>
- <param-name>encoding</param-name>
- <param-value>GBK</param-value>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>Set Character Encoding</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
(3).完成。
get方式的解决办法:
(1).打开tomcat的server.xml文件,找到区块,加入如下一行:URIEncoding="UTF-8"
完整的应如下:
- <Connector
- port="80" maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
- enableLookups="false" redirectPort="8443" acceptCount="100"
- debug="0" connectionTimeout="20000"
- disableUploadTimeout="true"
- URIEncoding="UTF-8" />
(2).重启tomcat,一切OK。
3、XMLHttpRequest中文问题
页面jsp用的UTF-8编码:
代码
- <%@ page contentType="text/html; charset=GBK"%>
javascript部分:
- function addFracasReport() {
- var url="servlet/encodingServlet";
- //var urlmsg="&reportId="+fracasReport1.textReportId.value; //故障报告表编号
- var xmlHttp=createXmlHttpRequest() ;
- xmlHttp.onreadystatechange = function(){
- //对象的状态为4表示已完成
- if(xmlHttp.readyState==4){
- //成功返回200,没有修改返回304
- if(xmlHttp.status==200||xmlHttp.status==304){
- //开始处理信息
- //alert(xhr.responseText) ;
- alert("请求发送成功") ;
- }
- }
- }
- xmlHttp.open("POST",url,true);
- xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
- var urlmsg = "hello=你好&world=世界"
- xmlHttp.send(urlmsg);
- }
此时,如果前台引用JS代码的JSP页面用的全部是UTF-8编码,那么在后获取时,不会出现乱码问题,例如在Servlet中用String hello = request.getParameter("hello") ;获取并用System.out.println(hello) ;输出到控制台上.但是如果用response.getWriter().print(hello);输出到页面上的话,会出现乱码问题,此时可以在Servlet中用response.setCharacterEncoding("UTF-8") ;进行转码.
4、toad的字符集的设置与oracle的安装
oracle数据库服务器的安装一般是中文字符集,有时安装在不同的平台下,设置为ISO编码,toad是oracle开发的最好工具,不是我说的,可是中文环境下安装的toad,打开英文字符的oracle时,中文全是乱码。必须进行设置.
环境变量->系统变量
加NLS_lANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
或
NLS_lANG=AMERICAN_AMERICA.WE8ISO8859P1 AMERICAN_AMERICA.WE8MSWIN1252
或者
打开注册表,点击HKEY_LOCAL_MATHINE再点击Software,再点击ORACLE在点击HOME(ORACLE所在目录)在注册表的右半面有NLS_LANG,双击它,将你想要的覆盖掉原来的就可以了最好记下旧的,以便可以改回来。
- connect sys/change_on_install
- update props$
- set value$='ZHS16CGB231280'
- where name='NLS_CHARACTERSET';
- commit;
这样就OK了
5.如何解決GWT(google web toolkit)中文的问题
GWT 中文乱码解决方法
(1).把你要显示的中文“测试字符串”输入到一个文件,如:1.txt
(2).进入命令行,进入1.txt所在的目录,敲入以下命令:native2ascii.exe 1.txt 2.txt 回车。这样就生成了另外一个文件2.txt。
(3).2.txt的内容如下:\u6d4b\u8bd5\u5b57\u7b26\u4e32
(4).然后用上面的编码,在gwt中使用,就可以了.
6.xmlHttp得到的网页怎么是乱码?
(1).在服务器端使用WebRequest而不是xmlHttp.
(2).将StreamReader sr = new StreamReader(stream);
对于简体中文改成:
StreamReader sr = new StreamReader(stream , Encoding.Default );
对于utf-8改成:
StreamReader sr = new StreamReader(stream , Encoding.UTF8 );
当然,Encoding枚举还有很多其他的成员,对于不同的编码content-type可以有选择的应用
(3).后来我发现无论是content-type是gb2312还是utf-8,用
StreamReader sr = new StreamReader(stream , Encoding.Default );
都可以返回正常的汉字,所以统一的改成Encoding.Default
最后,在服务器端从一个url获得网页的源代码的代码如下:
- /// <summary>
- /// post一个指定的url,获得网页的源代码(用WebRequest实现)
- /// </summary>
- /// <param name="url"></param>
- /// <returns>
- /// 如果请求失败,返回null
- /// 如果请求成功,返回网页的源代码
- /// </returns>
- public static string GetContentFromUrl2( string url )
- {
- //变量定义
- string respstr;
- WebRequest myWebRequest=WebRequest.Create(url);
- // myWebRequest.PreAuthenticate=true;
- // NetworkCredential networkCredential=new NetworkCredential( username , password , domain );
- // myWebRequest.Credentials=networkCredential;
- // Assign the response object of 'WebRequest' to a 'WebResponse' variable.
- WebResponse myWebResponse=myWebRequest.GetResponse();
- System.IO.Stream stream = myWebResponse.GetResponseStream();
- StreamReader sr = new StreamReader(stream , Encoding.Default );
- //以字符串形式读取数据流
- respstr = sr.ReadToEnd();
- sr.Close();
- return respstr;
- }
7.解决weblogic/webshpere中文问题:
在web.xml文件中需要配置中文环境。如下:
- <context-param>
- <param-name>weblogic.httpd.inputCharset./*</param-name>
- <param-value>GB2312</param-value>
- </context-param>
20120228补充如下:
8.利用JS过渡,在Java类中转码接收(适用WebSphere).
- // 前台JS代码如下
- var url = strAction+"?method=startProc&proName="+encodeURI(encodeURI('要传的汉字'));
- // 后台Action中解码如下
- zjmc = java.net.URLDecoder.decode('要传的汉字',"UTF-8");
- System.out.println(zjmc) ;
解决HttpServletResponse输出的中文乱码问题
首先,response返回有两种,一种是字节流outputstream,一种是字符流printwrite。
申明:这里为了方便起见,所有输出都统一用UTF-8编码。
先说字节流,要输出“中国",给输出流的必须是转换为utf-8的“中国”,还要告诉浏览器,用utf8来解析数据
- //这句话的意思,是让浏览器用utf8来解析返回的数据
- <strong style="background-color: #ffff66;">response</strong>.setHeader("Content-type", "text/html;charset=UTF-8");
- String data = "中国";
- OutputStream ps = <strong style="background-color: #ffff66;">response</strong>.getOutputStream();
- //这句话的意思,使得放入流的数据是utf8格式
- ps.write(data.getBytes("UTF-8"));
再说字符流,要输出中国,需要设置response.setCharacterEncoding("UTF-8");
- //这句话的意思,是让浏览器用utf8来解析返回的数据
- <strong style="background-color: #ffff66;">response</strong>.setHeader("Content-type", "text/html;charset=UTF-8");
- //这句话的意思,是告诉servlet用UTF-8转码,而不是用默认的ISO8859
- <strong style="background-color: #ffff66;">response</strong>.setCharacterEncoding("UTF-8");
- String data = "中国";
- PrintWriter pw = <strong style="background-color: #ffff66;">response</strong>.getWriter();
- pw.write(data);
经验:
1,如果中文返回出现??字符,这表明没有加response.setCharacterEncoding("UTF-8");这句话。
2,如果返回的中文是“烇湫”这种乱码,说明浏览器的解析问题,应该检查下是否忘加response.setHeader("Content-type", "text/html;charset=UTF-8");这句话。
最后 还有更好的服务器端出现传输乱码问题。最好的解决方案
将包含汉字的字符串转换成英文:
- /**
- * 将中英文字串转换成纯英文字串
- * @param str
- * @return
- */
- public static String toTureAsciiStr(String str) {
- StringBuffer sb = new StringBuffer();
- byte[] bt = str.getBytes();
- for(int i =0 ;i<bt.length;i++){
- if(bt[i]<0){
- //是汉字去高位1
- sb.append((char)(bt[i] & 0x7F));
- }else{
- //是英文字符 补0作记录
- sb.append((char)0);
- sb.append((char)bt[i]);
- }
- }
- return sb.toString();
- }
将转换后的字符串还原:
- /**
- * 将经转换的字串还原
- * @param str
- * @return
- */
- public static String unToTrueAsciiStr(String str){
- byte[] bt = str.getBytes();
- int i,l=0,length = bt.length,j=0;
- for(i = 0;i<length;i++){
- if(bt[i] == 0){
- l++;
- }
- }
- byte[] bt2 = new byte[length-l];
- for(i =0 ;i<length;i++){
- if(bt[i] == 0){
- i++;
- bt2[j] = bt[i];
- }else{
- bt2[j] = (byte)(bt[i]|0x80);
- }
- j++;
- }
- String tt = new String(bt2);
- return tt;
- }
注意:上例在实际编程中效果很好,只是存储的中文信息需要经过同样处理,才能被其他系统使用。而且如果中文字串出现英文字符,实际上增加了额外的存储空间。