Java中文问题一直困扰着很多初学者,如果了解了Java系统的中文问题原理,我们就可以对中文问题能够采取根本的解决之道。
n
HTTP
传输编码用
ISO88-59-1,
一些数据库如
SQLServer2000
等的默认编码也是
ISO88-59-1
n
通常我们在服务器的
Jsp,Html
或者
Servlet
中的编码方式为
GB2312,GBK,UTF-8
等,
如
<meta http-equiv="Content-Type" content="text/html; charset=GBK">
<%@ page contentType="text/html; charset=gb2312" language="java" %>
n
有的时候显示可能没有问题,但遇到数据的传输可能会出现乱码
JSP
的汉字问题出现环节
n
客户端显示文档时的编码方式(由服务器中的
JSP
Servlet
指明)
n
客户端发送汉字时自动转换为
iso-8859-1
n
服务器中采用
gb2312
对汉字编码,接收到客户端汉字需要转换为
gb2312
n
服务器端将
JSP
转换为
Servlet
时自动将汉字转换为
iso-8859-1
n
服务器端应该告诉客户端汉字的编码方式
n
JSP
中的汉字字符串在服务器端用
gb2312
n
在编译为
Servlet
时自动转换为
iso-8859-1
n
在没有特别指示下,浏览器中无法正确显示
解决方案
为解决单独页面显示方面的问题可以使用以下方案
n
在
HTML
中指示浏览器文档的编码
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
n
在
JSP
中指示
JSP
引擎文档的编码,每个要显示汉字的
JSP
文档都应该包含该语句
<%@ page contentType="text/html;charset=gb2312"%>
n
在
Servle
中加入以下代码
response.setContentType("text/html;charset=GB2312");
n
但数据在传输的时候可能又会变成乱码,这时候我们需要在接受的页面中加入
request.setCharacterEncoding("GB2312");
或者使用最古老的解决方案是使用String的字节码转换,这种方案问题是不方便,我们需要破坏对象封装性,进行字节码转换。
public class trans {
public static String trans(String str)
{
String result = null;
byte temp [];
try
{
temp=str.getBytes("iso-8859-1");
result = new String(temp);
}
catch(UnsupportedEncodingException e)
{
System.out.println (e.toString());
}
return result;
}
}
还有一种方式是对
J2EE
容器进行编码设置,如果
J2EE
应用系统脱离该容器,则会发生乱码,而且指定容器配置不符合
J2EE
应用和容器分离的原则。
在
Java
内部运算中,涉及到的所有字符串都会被转化为
UTF-8
编码来进行运算。那么,在被
Java
转化之前,字符串是什么样的字符集?
Java总是根据操作系统的默认编码字符集来决定字符串的初始编码,而且Java系统的输入和输出的都是采取操作系统的默认编码。
因此,如果能统一
Java
系统的输入、输出和操作系统
3
者的编码字符集合,将能够使
Java
系统正确处理和显示汉字。这是处理
Java
系统汉字的一个原则,但是在实际项目中,能够正确抓住和控制住
Java
系统的输入和输出部分是比较难的。
J2EE
中,由于涉及到外部浏览器和数据库等,所以中文问题乱码显得非常突出。
J2EE
应用程序是运行在
J2EE
容器中。在这个系统中,输入途径有很多种:一种是通过页面表单打包成请求(
request
)发往服务器的;第二种是通过数据库读入;还有第
3
种输入比较复杂,
JSP
在第一次运行时总是被编译成
Servlet,JSP中常常包含中文字符,那么编译使用javac时,Java将根据默认的操作系统编码作为初始编码。除非特别指定,如在Jbuilder/eclipse中可以指定默认的字符集。
输出途径也有几种:第一种是
JSP
页面的输出。由于
JSP
页面已经被编译成
Servlet
,那么在输出时,也将根据操作系统的默认编码来选择输出编码,除非指定输出编码方式;还有输出途径是数据库,将字符串输出到数据库。
由此看来,一个
J2EE
系统的输入输出是非常复杂,而且是动态变化的,而
Java
是跨平台运行的,在实际编译和运行中,都可能涉及到不同的操作系统,如果任由
Java
自由根据操作系统来决定输入输出的编码字符集,这将不可控制地出现乱码。
正是由于
Java
的跨平台特性,使得字符集问题必须由具体系统来统一解决,所以在一个
Java
应用系统中,解决中文乱码的根本办法是明确指定整个应用系统统一字符集。
指定统一字符集时,到底是指定
ISO-8859-1 ,
GB2312
还是
UTF-8
呢?
1.
如统一指定为
ISO-8859-1
,因为目前大多数软件都是西方人编制的,他们默认的字符集就是
ISO-8859-1,包括操作系统Linux和数据库MySQL等。这样,如果指定Jive统一编码为ISO-8859-1,那么就有下面3个环节必须把握:
<1>.开发和编译代码时指定字符集为
ISO-8859-1,
<2>.运行操作系统的默认编码必须是
ISO-8859-1,如Linux。
<3>.在
JSP
头部声明:
<%@ page contentType="text/html;charset=ISO-8859-1" %>
2.
如果统一指定为
GB2312
中文字符集,上述
3
个环节同样需要做到,不同的是只能运行在默认编码为
GBK
的操作系统,如中文
Windows
。
统一编码为
ISO-8859-1
和
GB2312
虽然带来编制代码的方便,但是各自只能在相应的操作系统上运行。但是也破坏了
Java
跨平台运行的优越性,只在一定范围内行得通。例如,为了使得
GB2312
编码在
linux
上运行,设置
Linux
编码为
GB2312
。
那么有没有一种除了应用系统以外不需要进行任何附加设置的中文编码根本解决方案呢?
将
Java/J2EE
系统的统一编码定义为
UTF-8
,
UTF-8
编码是一种兼容所有语言的编码方式,惟一比较麻烦的就是要找到应用系统的所有出入口,然后使用
UTF-8
去 "结扎"它。
一个
J2EE
应用系统需要做下列几步工作:
开发和编译代码时指定字符集为
UTF-8 ,JBuilder和Eclipse都可以在项目属性中设置。
使用过滤器,如果所有请求都经过一个
Servlet
控制分配器,那么使用
Servlet
的
filter
执行语句,将所有来自浏览器的请求(
request
)转换为
UTF-8
,因为浏览器发过来的请求包根据浏览器所在的操作系统编码,可能是各种形式编码。关键一句:
request.setCharacterEncoding("UTF-8")
public class SetCharacterEncodingFilter implements Filter {
protected String encoding = null;
protected FilterConfig filterConfig = null;
public void destroy() {
this.encoding = null;
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding(encoding);
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
}
protected String selectEncoding(ServletRequest request) {
return (this.encoding);
}
}
需要配置
web.xml
激活该
Filter
<filter>
<filter-name>SetCharacterEncodingFilter</filter-name>
<filter-class>com.yinhe.Filter.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SetCharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在
JSP
头部声明:
<%@ page contentType="text/html;charset= UTF-8" %>
在
JSP
的
html
代码中,声明
UTF-8:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
设定数据库连接方式是
UTF-8
,例如连接
MYSQL
时配置
URL
如下:
jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8
一般数据库都可以通过管理设置设定
UTF-8
其他和外界交互时能够设定编码时就设定
UTF-8,例如读取文件,操作XML等。