论坛首页 Java版 Webwork

jsp, java, 数据库三者之间字符集转换的深度讨论

浏览 13501 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
时间:2006-08-04
关于三者之间的中文乱码问题,各大论坛都讨论过不少了,但是很多都是给矛了针对某种转换的解决办法,有的搞了几年开发,对这个问

题的原理,三者之间的转换关系,还是比较模糊的,包括我自己. 于是今天下决心砌底地把这个web应用中最常见的问题搞明白,请各位达人指点一下。

根据以往的经验,这种中文乱码问题,都是由于jsp,java,数据库三者之前的编码不同造成的,jsp的编码是在
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*"%>
中设定的,java文件中的字符串编码,众所周知是unicode的,而数据表的字符编码,也是可以设定的。

好了,我先开了个头了,现在我想通过几个例子来让大家讨论有个焦点。

程序的流程是这样的,我们先从java文件中读到数据库中的中文字符,然后,在jsp页面上,用<jsp:useBean />标签来取出字符,并out.println()显示出来。


例1 如果jsp的CHARSET=utf8,数据库的字符编码也是GBK的,三者之间的编码转换的过程是怎样的?

例2 如果jsp的charset=UTF-8, 数据库的字符编码是GBK呢?

例3 如果jsp的charset=UTF-8,数据库中的字符编码也是UTF-8的呢?

其实,最重要的是原理跟过程,希望大家把自己知道的都说出来,能让别人或自己在此贴中学习到一些之前忽略了的东西就够了。


顺便提两个小问题:

1 jsp页头的,charset和pageEncoding这两者的作用分别是什么呢?

2

前后两个页面的charset的不同,对request对象的characterEncoding又有什么决定影响呢?因为常常见到request.setCharacterEncoding("GB2312");的。
   
时间:2006-08-04
java 的 editor 比如,Eclipse IDE 也有 charset。
jsp 的editor ,比如,dreamweaver, notepad,也有charset。

编译java, jsp用的javac的命令行有 encoding charset,用来说明source code采用什么charset。

可见,jsp, java 由于涉及到编译器问题,最好不要把字符串资源直接放到 java, jsp code里面。尤其是欧美字符体系之外的双字节字符串。
我看到有相反的看法,有人竟然提议,不要用html存放字符串资源,要用jsp存放字符串资源。感到很奇怪。

字符串资源,应该尽量放到 html, 或者其他资源文件中,比如,xml,properties。等。
这些资源文件,只需要设定editor的encoding就行了,不需要照看编译器的encoding。

html header

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

这个是告诉浏览器选择 charset。

request.setCharaterEncoding() 设置的是浏览器过来的charset。

response.setCharaterEncoding() 设置的是去浏览器的 charset。

----

browser,
editor,
compiler,

这些地方都要考虑charset.
   
0 请登录后投票
时间:2006-08-05
楼上所讲的,就是我正在思考的问题, 今天我做了个实验,发现了一个有趣的现象,如果在java文件中,设定了String变量的值为中文,

[code:1]public class testEncoding
{
String s="哈哈";
public String getS()
{
return s;
}

}[/code:1]
那么,我在jsp页面中采用
[code:1]<jsp:useBean id="test"......./>
<%
out.println(test.getS());
%>[/code:1]

出来的结果,是乱码的,无论我把jsp页头的charset改为什么都一样。然后,我把java程序改了一下,变为

[code:1]public class testEncoding
{
String s="哈哈";
public String getS()
{
return UTF8Encode(s);
}

public static String UTF8Encode(String s_string)
{
try
{
String des=new String(s_string.getBytes("GBK"),"UTF-8");
return des;
}
catch(Exception ex)
{
String des="";
return des; }
}

}[/code:1]

这样,出来的结果就不会乱码了。出现这样结果的原理很明显,JDK编译java文件里,把里面的所有字符都当成是unicode编码的,但是在我们编写这个JAVA文件时,输入法输入的字符是按GBK编码的,所以要把字符转成UTF-8(变长型的unicode),编译后才能被正常读出。
   
0 请登录后投票
时间:2006-08-05
但是,也有另外一个有趣的现象

[code:1]<%@ page language="java" contentType="text/html; charset=big5"
pageEncoding="big5"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%out.println(showS()); %>
<%!
public String showS()
{
String s="哈哈";
return s;
}

%>
</body>
</html>[/code:1]

众所周知,jsp最后也要编译成Servlet文件,才能执行的,也就是说,也要通过JDK来编译的,但以上代码,却是不用作任何的转换,都可以正常显示“哈哈”,起初,我以为是jsp的charset造成容器自动完成转换过程,后来,我把charset=big5了,但是,照样能正常显示“哈哈”,这个我就费解了,为什么java文件中的中文字符,要转成utf-8,而jsp中的却不同了,明明都是通过JDK来编译的。 请哪位高手能解释一下的。
   
0 请登录后投票
时间:2006-08-05
Terry_Yipp,你的操作系统是哪个语言的,省却的file.encoding是什么?不把这个问题搞清楚无法讨论实验结果。

可用下列代码查查:



[code:1]import java.util.*;

public class Test {
public static void main(String[] args) {
Properties properties = System.getProperties();
System.out.println(Properties.getProperty("file.encoding"));
}
}[/code:1]
   
0 请登录后投票
时间:2006-08-05
先谈谈charset和pageEncoding.

O'Reily的Java Server Pages 第三版这么说:

引用
pageEncoding:The encoding used for the JSP page file, as well as
the response charset if no charset is specified by contentType.

If this attribute is omitted, but a charset is specified for contentType,
that charset is also used of the page; if contentType doesn't specify a
charset, ISO-8859-1 is used for a regular JSP page, and UTF-8 is used
for a JSP Document.


要从头讲起话就长了。要把这个问题讨论的比较清楚涉及到UTF-8, GBK一大堆标准,慢慢讨论下去吧。
   
0 请登录后投票
时间:2006-08-05
请问哪位师傅能告诉我以下异常是什么意思?
(工具jBuilder,数据库SQLServer,jsp页面请求时发生异常,我肯定代码没问题,是哪里配置出错了吗?急!Tomcat5.5)


java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC]Error establishing socket.
at com.microsoft.jdbc.base.BaseExceptions.createException(Unknown Source)
at com.microsoft.jdbc.base.BaseExceptions.getException(Unknown Source)
at com.microsoft.jdbc.base.BaseExceptions.getException(Unknown Source)
at com.microsoft.jdbc.sqlserver.tds.TDSConnection.<init>(Unknown Source)
at com.microsoft.jdbc.sqlserver.SQLServerImplConnection.open(Unknown Source)
at com.microsoft.jdbc.base.BaseConnection.getNewImplConnection(Unknown Source)
at com.microsoft.jdbc.base.BaseConnection.open(Unknown Source)
at com.microsoft.jdbc.base.BaseDriver.connect(Unknown Source)
at java.sql.DriverManager.getConnection(DriverManager.java:525)
at java.sql.DriverManager.getConnection(DriverManager.java:171)
at org.apache.jsp.verifyLoginPage_jsp._jspService(org.apache.jsp.verifyLoginPage_jsp:68)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:322)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:291)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:241)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:744)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
at java.lang.Thread.run(Thread.java:595)
   
0 请登录后投票
时间:2006-08-05
引用

Error establishing socket.


是说连接数据库进程失败,你的数据库是不是在正常运行啊?
   
0 请登录后投票
时间:2006-08-06
TO liuzibaobei:请尊重别人,不要在别人的贴子中,问一些和本贴无关的问题,如果你想知道你的问题的答案,请另外开贴发问。
谢谢。
   
0 请登录后投票
时间:2006-08-06
bigpanda 写道
Terry_Yipp,你的操作系统是哪个语言的,省却的file.encoding是什么?不把这个问题搞清楚无法讨论实验结果。




是GBK的。
   
0 请登录后投票
论坛首页 Java版 Webwork

跳转论坛:
JavaEye推荐