??xml version="1.0" encoding="utf-8" standalone="yes"?>
1、中文问题的来源
计算机最初的操作pȝ支持的编码是单字节的字符~码Q于是,在计机中一切处理程序最初都是以单字节编码的英文为准q行处理。随着计算机的发展Qؓ了适应世界其它民族的语aQ当然包括我们的汉字Q,Z提出了UNICODE~码Q它采用双字节编码,兼容英文字符和其它民族的双字节字W编码,所以,目前Q大多数国际***的Y件内部均采用UNICODE~码Q在软gq行Ӟ它获得本地支持系l(多数旉是操作系l)默认支持的编码格式,然后再将软g内部?UNICODE转化为本地系l默认支持的格式昄出来。Java的JDK和JVMx如此Q我q里说的JDK是指国际版的JDKQ我们大多数E序员用的是国际化的JDK版本Q以下所有的JDK均指国际化的JDK版本。我们的汉字是双字节~码语言Qؓ了能让计机处理中文Q我们自己制定的gb2312?GBK、GBK2K{标准以适应计算机处理的需求。所以,大部分的操作pȝZ适应我们处理中文的需求,均定制有中文操作pȝQ它们采用的是GBK, GB2312~码格式以正显C我们的汉字。如Q中文Win2K默认采用的是GBK~码昄Q在中文WIN2k中保存文件时默认采用的保存文件的~码格式也是GBK的,卻I所有在中文WIN2K中保存的文g它的内部~码默认均采用GBK~码Q注意:GBK是在GB2312基础上扩充来的?/font>
׃Java语言内部采用UNICODE~码Q所以在JAVAE序q行Ӟ存在着一个从UNICODE~码和对应的操作pȝ及浏览器支持的编码格式{换输入、输出的问题Q这个{换过E有着一pd的步骤,如果其中M一步出错,则显C出来的汉字׃出是qQ这是我们常见的JAVA中文问题?/font>
同时QJava是一个跨q_的编E语aQ也x们编写的E序不仅能在中文windows上运行,也能在中文Linux{系l上q行Q同时也要求能在英文{系l上q行Q我们经常看到有人把在中文win2k上编写的JAVAE序Q移植到英文Linux上运行)。这U移植操作也会带来中文问题?/font>
q有Q有Z用英文的操作pȝ和英文的IE{浏览器Q来q行带中文字W的E序和浏览中文网,它们本n׃支持中文Q也会带来中文问题?/font>
几乎所有的览器默认在传递参数时都是以UTF-8~码格式来传递,而不是按中文~码传递,所以,传递中文参数时也会有问题,从而带来ؕ码现象?/font>
MQ以上几个方面是JAVA中的中文问题的主要来源,我们把以上原因造成的程序不能正运行而生的问题UCQJAVA中文问题?/font>
2、JAVA~码转换的详l过E?
我们常见的JAVAE序包括以下cdQ?br /> *直接在console上运行的c?包括可视化界面的c?
q些cL件中Q都有可能含有中文字W串Qƈ且我们常用前三类JAVAE序和用L接交互,用于输出和输入字W,如:我们在JSP和Servlet中得到客L送来的字W,q些字符也包括中文字W。无些JAVAcȝ作用如何Q这些JAVAE序的生命周期都是这LQ?/font>
*~程人员在一定的操作pȝ上选择一个合适的~辑软g来实现源E序代码q以.java扩展名保存在操作pȝ中,例如我们在中文win2k中用C本编辑一个java源程序;
q里Q我们以中文win2k操作pȝZ说明JAVAcL如何来编码和被解码的?
W一步,我们在中文win2k中用~辑软g如记事本~写一个Java源程序文?包括以上五类JAVA E序)Q程序文件在保存旉认采用了操作pȝ默认支持GBK~码格式(操作pȝ默认支持的格式ؓfile.encoding格式)形成了一?java文gQ也卻IjavaE序在被~译前,我们的JAVA源程序文件是采用操作pȝ默认支持的file.encoding~码格式保存的,java源程序中含有中文信息字符和英文程序代码;要查看系l的file.encoding参数Q可以用以下代码Q?br /> public class ShowSystemDefaultEncoding {
W二步,我们用JDK的javac.exe文g~译我们的Java源程序,׃JDK是国际版的,在编译的时候,如果我们没有?encoding参数指定我们?JAVA源程序的~码格式Q则javac.exe首先获得我们操作pȝ默认采用的编码格式,也即在编译javaE序Ӟ若我们不指定源程序文件的~码格式QJDK首先获得操作pȝ的file.encoding参数(它保存的是操作pȝ默认的编码格式,如WIN2kQ它的gؓGBK)Q然后JDK把我们的java源程序从file.encoding~码格式转化为JAVA内部默认?UNICODE格式攑օ内存中。然后,javac把{换后的unicode格式的文件进行编译成.classcLӞ此时.class文g?UNICODE~码的,它暂攑֜内存中,紧接着QJDK此以UNICODE~码的编译后的class文g保存到我们的操作pȝ中Ş成我们见到的. class文g。对我们来说Q我们最l获得的.class文g是内容以UNICODE~码格式保存的类文gQ它内部包含我们源程序中的中文字W串Q只不过此时它己l由file.encoding格式转化为UNICODE格式了?/font>
q一步中Q对于JSP源程序文件是不同的,对于JSPQ这个过E是q样的:即WEB容器调用JSP~译器,JSP~译器先查看JSP文g中是否设|有文g~码格式Q如果JSP文g中没有设|JSP文g的编码格式,则JSP~译器调用JDK先把JSP文g用JVM默认的字W编码格?也即WEB容器所在的操作pȝ的默认的file.encoding)转化Z时的Servletc,然后再把它编译成UNICODE格式的classc,q保存在临时文g夹中。如Q在中文win2k上,WEB容器把JSP文g从GBK~码格式转化为UNICODE格式Q然后编译成临时保存的Servletc,以响应用Lh?/font>
W三步,q行W二步编译出来的c,分ؓ三种情况Q?/strong>
A?直接在console上运行的c?br /> B?EJBcd不可以直接运行的支持c?如JavaBeanc?
q种情况Q运行该c首先需要JVM支持Q即操作pȝ中必d装有JRE。运行过E是q样的:首先java启动JVMQ此时JVMd操作pȝ中保存的 class文gq把内容d内存中,此时内存中ؓUNICODE格式的classc,然后JVMq行它,如果此时此类需要接收用戯入,则类会默认用 file.encoding~码格式对用戯入的串进行编码ƈ转化为unicode保存入内存(用户可以讄输入的~码格式Q。程序运行后Q生的字符ԌUNICODE~码的)再回交给JVMQ最后JRE把此字符串再转化为file.encoding格式(用户可以讄输出的~码格式)传递给操作pȝ昄接口q输出到界面上?/font>
对于q种直接在console上运行的c,它的转化q程可用?更加明确的表C出来:
?
以上每一步的转化都需要正的~码格式转化Q才能最l不出现q现象?br />
?
l过W二步后QJSP文g也被转化为ServletscLӞ只不q它不像标准的Servlets一校存在于classes目录中,它存在于WEB容器的时目录中Q故q一步中我们也把它做为Servlets来看?/font>
对于ServletsQ客Lh它时QWEB容器调用它的JVM来运行ServletQ首先,JVM把Servlet的classcMpȝ中读出ƈ装入内存中,内存中是以UNICODE~码的Servletcȝ代码Q然后JVM在内存中q行该Servletc,如果Servlet在运行的q程中,需要接受从客户端传来的字符如:表单输入的值和URL中传入的|此时如果E序中没有设定接受参数时采用的编码格式,则WEB容器会默认采用ISO-8859- 1~码格式来接受传入的值ƈ在JVM中{化ؓUNICODE格式的保存在WEB容器的内存中。Servletq行后生成输出,输出的字W串?UNICODE格式的,紧接着Q容器将Servletq行产生的UNICODE格式的串Q如html语法Q用戯出的串等Q直接发送到客户端浏览器上ƈ输出l用P如果此时指定了发送时输出的编码格式,则按指定的编码格式输出到览器上Q如果没有指定,则默认按ISO-8859-1~码发送到客户的浏览器上。这UJSP代码和Servletc,它的转化q程可用?更加明确地表C出来:
?
D、JavaE序和数据库之间
对于几乎所有数据库的JDBC驱动E序Q默认的在JAVAE序和数据库之间传递数据都是以ISO-8859-1为默认编码格式的Q所以,我们的程序在向数据库内存储包含中文的数据ӞJDBC首先是把E序内部的UNICODE~码格式的数据{化ؓISO-8859-1的格式,然后传递到数据库中Q在数据库保存数据时Q它默认即以ISO-8859-1保存Q所以,q是Z么我们常常在数据库中d的中文数据是q?br /> 对于JAVAE序和数据库之间的数据传递,我们可以用图4清晰地表C出?/font>
?
再次Q对于放在操作系l中?java源程序文Ӟ在编译时Q我们可以指定它内容的编码格式,具体来说?encoding来指定。注意:如果源程序中含有中文字符Q而你?encoding指定为其它的~码字符Q显然是要出错的。用-encoding指定源文件的~码方式为GBK或gb2312Q无论我们在什么系l上~译含有中文字符的JAVA源程序都不会有问题,它都会正地中文{化ؓUNICODE存储在class文g中?br />
了解以上JAVA处理文g的原理之后,我们可以提Z一套徏议最优的解决汉字问题的办法?br /> 我们的目标是Q我们在中文pȝ中编辑的含有中文字符串或q行中文处理的JAVA源程序经~译后可以移值到M其它?/font>
操作pȝ
中正运行,或拿到其它操作系l中~译后能正确q行Q能正确C递中文和英文参数Q能正确地和
数据?/font>
交流中英文字W串?br /> 我们的具体思\是:在JAVAE序转码的入口和出口及JAVAE序同用h输入输出转换的地斚w制编码方法之正即可?/font>
具体解决办法如下Q?/strong>
1?针对直接在console上运行的c?/strong>
//Read.java
?
׃q种cd们本w被其它的类调用Q不直接与用户交互,故对q种cL_我们的徏议的处理方式是内部程序中应该采用字符来处理E序内部的中文字W串Q具体如上面一节中一PQ同Ӟ在编译类时用-encoding gb2312参数指示源文件是中文格式~码的即可?/font>
针对ServletQ我们徏议用以下ҎQ(我徏议将.java文g讄为UTF8~码的。当然如果是用Eclipse的话Q只要设|下是了。对于数据库Q我以ؓ~码最好设|ؓUTF8,便于国际化 。尽可能的用UTF8码, 千里草)
在编译Servletcȝ源程序时Q用-encoding指定~码为GBK或GB2312Q且在向用户输出时的~码部分用response对象?setContentType("text/html;charset=GBK");或gb2312来设|输出编码格式,同样在接收用戯入时Q我们用 request.setCharacterEncoding("GB2312")Q这h论我们的servletcȝ植到什么操作系l中Q只有客L的浏览器支持中文昄Q就可以正确昄。如下是一个正的CZQ?/font>
//HelloWorld.java
<body bgcolor="#FFFFFF" text="#000000" topmargin="5">
?
为避免JAVAE序和数据库之间数据传递出Cؕ码现象,我们采用以下最优方法来处理Q?br /> 1?对于JAVAE序的处理方法按我们指定的方法处理?br /> 2?把数据库默认支持的编码格式改为GBK或GB2312的?/font>
如:在mysql中,我们可以在配|文件my.ini中加入以下语句实玎ͼ
5?针对JSP代码
׃JSP是在q行Ӟ由WEB容器q行动态编译的Q如果我们没有指定JSP源文件的~码格式Q则JSP~译器会获得服务器操作系l的 file.encoding值来对JSP文g~译的,它在UL时最Ҏ出问题,如在中文win2k中可以很好运行的jsp文g拿到英文linux中就不行Q尽客L都是一LQ那是因为容器在~译JSP文g时获取的操作pȝ的编码不同造成的(在中文wink中的file.encoding和在英文 Linux中file.encoding是不同的Q且英文Linux的file.encoding对中文不支持Q所以编译出来的JSPcd会有问题Q?/font>
|络
上讨论的大多数是此类问题Q多是因为JSP文gULq_时不能正显C的问题Q对于这c问题,我们了解了JAVA中程序编码{换的原理Q解册v来就Ҏ多了。我们徏议的解决办法如下Q?/font>
1、我们要保证JSP向客L输出时是采用中文~码方式输出的,x论如何我们首先在我们的JSP源代~中加入以下一行:
<
%@page
contentType="text/html; charset=gb2312"%>
//testchinese.jsp
?
5、ȝ
在上面的详细分析中,我们清晰地给ZJAVA在处理源E序q程中的详细转换q程Qؓ我们正确解决JAVA~程中的中文问题提供了基。同Ӟ我们l出了认为是最优的解决JAVA中文问题的办法?/font>
*JSP代码c(注:JSP是Servletscȝ变型Q?br /> *Serveletsc?br /> *EJBc?br /> *其它不可以直接运行的支持c?/font>
*~程人员用JDK中的javac.exe来编译这些源代码QŞ?classc?JSP文g是由容器调用JDK来编译的)Q?br /> *直接q行q些cL这些类布v到WEB容器中去q行Qƈ输出l果?br /> 那么Q在q些q程中,JDK和JVM是如何将q些文g如何~码和解码ƈq行的呢Q?/font>
public static void main(String[] args) {
String encoding = System.getProperty("file.encoding");
System.out.println(encoding);
}}
C?JSP代码和Servletc?br /> D?JAVAE序和数据库之间
下面我们分这四种情况来看?br /> A、直接在console上运行的c?/strong>
B、EJBcd不可以直接运行的支持c?如JavaBeanc?
׃EJBcd不可以直接运行的支持c,它们一般不与用L接交互输入和输出Q它们常怸其它的类q行交互输入和输出,所以它们在W二步被~译后,Ş成了内容是UNICODE~码的类保存在操作系l中了,以后只要它与其它的类之间的交互在参数传递过E中没有丢失Q则它就会正的q行?br />q种EJBcd不可以直接运行的支持c? 它的转化q程可用?更加明确的表C出来:
C、JSP代码和Servletc?/strong>
3、分析常见的JAVA中文问题几个必须清楚的原?br />
首先Q经q上面的详细分析Q我们可以清晰地看到QQ何JAVAE序的生命期中,其编码{换的关键q程是在于:最初编译成class文g的{码和最l向用户输出的{码过E?br /> 其次Q我们必M解JAVA在编译时支持的、常用的~码格式有以下几U:
*ISO-8859-1Q?-bit, ?859_1,ISO-8859-1,ISO_8859_1{编?br /> *Cp1252Q美国英语编码,同ANSI标准~码
*UTF-8Q同unicode~码
*GB2312Q同gb2312-80,gb2312-1980{编?br /> *GBK , 同MS936Q它是gb2312的扩?br /> 及其它的~码Q如韩文、日文、繁体中文等。同Ӟ我们要注意这些编码间的兼容关体系如下Q?br /> unicode和UTF-8~码是一一对应的关pRGB2312可以认ؓ是GBK的子集,即GBK~码是在gb2312上扩展来的。同ӞGBK~码包含?0902个汉字,~码范围为:0x8140-0xfefeQ所有的字符可以一一对应到UNICODE2.0中来?/font>
然后Q我们必L楚,几乎所有的WEB容器在其内部默认的字W编码格式都是以ISO-8859-1为默认值的Q同Ӟ几乎所有的览器在传递参数时都是默认以UTF-8的方式来传递参数的。所以,虽然我们的Java源文件在出入口的地方指定了正的~码方式Q但其在容器内部q行时还是以ISO-8859- 1来处理的?br />
4、中文问题的分类及其最优解军_?/strong>
对于q种情况Q我们徏议在E序~写Ӟ如果需要从用户端接收用L可能含有中文的输入或含有中文的输出,E序中应该采用字W流来处理输入和输出Q具体来_应用以下面向字符型节ҎcdQ?br /> ҎӞFileReaderQFileWrieter
其字节型节点类型ؓQFileInputStreamQFileOutputStream
对内存(数组Q:CharArrayReaderQCharArrayWriter
其字节型节点类型ؓQByteArrayInputStreamQByteArrayOutputStream
对内存(字符ԌQStringReaderQStringWriter
对管道:PipedReaderQPipedWriter
其字节型节点类型ؓQPipedInputStreamQPipedOutputStream
同时Q应该用以下面向字符型处理流来处理输入和输出Q?br /> BufferedWriterQBufferedReader
其字节型的处理流为:BufferedInputeStreamQBufferedOutputStream
InputStreamReaderQOutputStreamWriter
其字节型的处理流为:DataInputStreamQDataOutputStream
其中InputStreamReader和InputStreamWriter用于字节流按照指定的字W编码集转换到字W流Q如Q?br /> InputStreamReader in = new InputStreamReader(System.inQ?GB2312")Q?br /> OutputStreamWriter out = new OutputStreamWriter (System.outQ?GB2312")Q?br /> 例如Q采用如下的CZJAVA~码pC要求Q?/font>
import java.io.*;
public class Read {
public static void main(String[] args) throws IOException {
String str = "\n中文试Q这是内部硬~码的串"+"\ntest english character";
String strin= "";
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in,"gb2312")); //讄输入接口按中文编?br /> BufferedWriter stdout = new BufferedWriter(new OutputStreamWriter(System.out,"gb2312")); //讄输出接口按中文编?br /> stdout.write("误?");
stdout.flush();
strin = stdin.readLine();
stdout.write("q是从用戯入的Ԍ"+strin);
stdout.write(str);
stdout.flush();
}}
同时Q在~译E序Ӟ我们用以下方式来q行Q?br /> javac -encoding gb2312 Read.java
其运行结果如?所C:
2?针对EJBcd不可以直接运行的支持c?如JavaBeanc?
3?针对Servletc?/font>
package hello;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWorld extends HttpServlet
{
public void init() throws ServletException { }
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
request.setCharacterEncoding("GB2312"); //讄输入~码格式
response.setContentType("text/html;charset=GB2312"); //讄输出~码格式
PrintWriter out = response.getWriter(); //使用PrintWriter输出
out.println("<hr>");
out.println("Hello World! This is created by Servlet!试中文!");
out.println("<hr>");
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
request.setCharacterEncoding("GB2312"); //讄输入~码格式
response.setContentType("text/html;charset=GB2312"); //讄输出~码格式
String name = request.getParameter("name");
String id = request.getParameter("id");
if(name==null) name="";
if(id==null) id="";
PrintWriter out = response.getWriter(); //使用PrintWriter输出
out.println("<hr>");
out.println("你传入的中文字串是:" + name);
out.println("<hr>你输入的id是:" + id);
out.println("<hr>");
}
public void destroy() { }
}
Ljavac -encoding gb2312 HelloWorld.java来编译此E序?br /> 试此Servlet的程序如下所C:
<%@page contentType="text/html; charset=gb2312"%>
<%request.setCharacterEncoding("GB2312");%>
<html><head><title></title>
<Script language="JavaScript">
function Submit() {
//通过URL传递中文字W串值给Servlet
document.base.action = "./HelloWorld?name=中文";
document.base.method = "POST";
document.base.submit();
}
</Script>
</head>
<form name="base" method = "POST" target="_self">
<input name="id" type="text" value="" size="30">
<a href = "JavaScript:Submit()">传给Servlet</a>
</form></body></html>
其运行结果如?所C:
4?JAVAE序和数据库之间
在[mysqld]区增加:
default-character-set=gbk
q增加:
[client]
default-character-set=gbk
在SQL Server2K中,我们可以数据库默认的语a讄为Simplified Chinese来达到目的?/font>
2、ؓ了让JSP能正获得传入的参数Q我们在JSP源文件头加入下面一句:
<%request.setCharacterEncoding("GB2312");%>
3、ؓ了让JSP~译器能正确地解码我们的含有中文字符的JSP文gQ我们需要在JSP源文件中指定我们的JSP源文件的~码格式Q具体来_我们在JSP源文件头上加入下面的一句即可:
<
%@page
pageEncoding="GB2312"%>?lt;
%@page
pageEncoding="GBK"%>
q是JSP规范2.0新增加的指o?br /> 我们使用此方法来解JSP文g中的中文问题Q下面的代码是一个正做法的JSP文g的测试程序:
<%@page pageEncoding="GB2312"%>
<%@page contentType="text/html; charset=gb2312"%>
<%request.setCharacterEncoding("GB2312");%>
<%
String action = request.getParameter("ACTION");
String name = "";
String str = "";
if(action!=null && action.equals("SENT"))
{
name = request.getParameter("name");
str = request.getParameter("str");
}
%>
<html>
<head>
<title></title>
<Script language="JavaScript">
function Submit()
{
document.base.action = "?ACTION=SENT&str=传入的中?;
document.base.method = "POST";
document.base.submit();
}
</Script>
</head>
<body bgcolor="#FFFFFF" text="#000000" topmargin="5">
<form name="base" method = "POST" target="_self">
<input type="text" name="name" value="" size="30">
<a href = "JavaScript:Submit()">提交</a>
</form>
<%
if(action!=null && action.equals("SENT"))
{
out.println("<br>你输入的字符为:"+name);
out.println("<br>你通过URL传入的字WؓQ?+str);
}
%>
</body>
</html>
如图7是此E序q行的结果示意图Q?br />
如果非要使用getҎ传form则要转换一下才行:
-----
<%@ page contentType="text/html;charset=gb2312"%>
<%!
public String getStr(String str){
try{
String temp_p=str;
byte[] temp_t=temp_p.getBytes("ISO8859-1");
String temp=new String(temp_t);
return temp;
}
catch(Exception e){
}
return "null";
}
%>
然后把String userId=request.getParameter("userId");Ҏ
String userId=getStr(request.getParameter("userId"));
Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-
我来说一下tomcat如何实现JSP的你明白了?br />预备知识Q?br /> 1.字节和unicode
Java内核是unicode的,pclass文g也是Q但是很多媒体,包括文g/的保存方式
是用字节流的?因此Java要对q些字节经行{化。char是unicode的,而byte是字?
Java中byte/char互{的函数在sun.io的包中间有。其中ByteToCharConvertercL中调度,
可以用来告诉你,你用的Convertor。其中两个很常用的静态函数是
public static ByteToCharConverter getDefault() ;
public static ByteToCharConverter getConverter(String encoding);
如果你不指定converterQ则pȝ会自动用当前的Encoding,GBq_上用GBK,ENq_上用
8859_1
我们来就一个简单的例子Q?br /> "?的gb码是Q?xC4E3 ,unicode?x4F60
你用:
--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]));
--}
--打印出来?x4F60
--但是如果使用8859_1的编码,打印出来?br /> --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
--如果?859_1是0x3FQ?P表示无法转化 --
很多中文问题是从这两个最单的cL生出来的。而却有很多类
不直接支持把Encoding输入Q这l我们带来诸多不ѝ很多程序难得用encoding
了,直接用default的encodingQ这q我们UL带来了很多困?br /> --
2.UTF-8
--UTF-8是和Unicode一一对应的,其实现很?br /> --
-- 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码是Q?xC4E3 ,unicode?x4F60
--我们q是用上面的例子
-- --例1Q?xC4E3的二q制Q?br /> -- -- 1 1 0 0 0 1 0 0 1 1 1 0 0 0 1 1
-- -- ׃只有两位我们按照两位的编码来排,但是我们发现q行不通,
-- -- 因ؓW7位不?因此Q返??"
-- --
-- --例2Q?x4F60的二q制Q?br /> -- -- 0 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0
-- -- 我们用UTF-8补齐Q变成:
-- -- 11100100 10111101 10100000
-- -- E4--BD-- A0
-- -- 于是q回0xE4,0xBD,0xA0
-- --
3.String和byte[]
--String其实核心是char[],然而要把byte转化成StringQ必ȝq编码?br /> --String.length()其实是char数组的长度,如果使用不同的编码,很可
--能会错分Q造成散字和ؕ码?br /> --例:
----byte [] b={(byte)'\u00c4',(byte)'\u00e3'};
----String str=new String(b,encoding); ----
----如果encoding=8859_1Q会有两个字Q但是encoding=gb2312只有一个字 ----
--q个问题在处理分|l常发生
4.Reader,Writer/InputStream,OutputStream
--Reader和Writer核心是charQInputStream和OutputStream核心是byte?br /> --但是Reader和Writer的主要目的是要把Char?写InputStream/OutputStream
--一个reader的例子:
--文gtest.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是gb2312Q则只有一个字W,如果encoding=8859_1Q则有两个字W?br /> --------
--
--
----
2.我们要对Java的编译器有所了解Q?br /> --javac -encoding
我们常常没有用到ENCODINGq个参数。其实Encodingq个参数对于跨^台的操作是很重要的?br /> 如果没有指定EncodingQ则按照pȝ的默认Encoding,gbq_上是gb2312Q英文^C是ISO8859_1。
--Java的编译器实际上是调用sun.tools.javac.Main的类Q对文gq行~译Q这个类 --
有compile函数中间有一个encoding的变?-encoding的参数其实直接传lencoding变量?br /> ~译器就是根据这个变量来djava文g的,然后把用UTF-8形式~译成class文g?br /> 一个例子:
--public void test()
--{
----String str="?;
----FileWriter write=new FileWriter("test.txt");
----write.write(str);
----write.close();
--}
----例3
--如果用gb2312~译Q你会找到E4 BD A0的字D?br />--
--如果?859_1~译Q?br />--00C4 00E3的二q制Q?br />--00000000 11000100 00000000 11100011--
--因ؓ每个字符都大?位,因此?1位编码:
--11000001 10000100 11000011 10100011
--C1-- 84-- C3-- A3
--你会扑ֈC1 84 C3 A3 --
但是我们往往忽略掉这个参敎ͼ因此q样往往会有跨^台的问题Q?br /> -- 例3在中文^C~译Q生成ZhClass
-- 例3在英文^C~译Q输出EnClass
--1. ZhClass在中文^C执行OK,但是在英文^C不行
--2. EnClass在英文^C执行OK,但是在中文^C不行
原因Q?br /> --1.在中文^C~译后,其实str在运行态的char[]?x4F60, ----
--在中文^Cq行QFileWriter的缺省编码是gb2312,因此
--CharToByteConverter会自动用调用gb2312的converter,把str转化
--成byte输入到FileOutputStream中,于是0xC4,0xE3放进了文件?br /> --但是如果是在英文q_下,CharToByteConverter的缺省值是8859_1,
--FileWriter会自动调?859_1去{化str,但是他无法解释,因此他会
--输出"?" ----
--2. 在英文^C~译后,其实str在运行态的char[]?x00C4 0x00E3, ----
--在中文^Cq行Q中文无法识别,因此会出??
-- 在英文^CQ?x00C4-->0xC4,0x00E3->0xE3Q因?xC4,0xE3被放q了
--文g
----
1.对于JSP正文的解释:
--Tomcat首先看一下你的叶面中有没?<
%@page
include的符受有Q则在相?br />--地方讑֮response.setContentType(..);按照encoding的来读,没有他按?859_1
--d文gQ然后用UTF-8写成.java文gQ然后用sun.tools.Main去读取这个文Ӟ
--Q当然它使用UTF-8去读Q,然后~译成class文g
--setContentType改变的是out的属性,out变量~省的encoding?859_1
2.对Parameter的解?br />--很不qParameter只有ISO8859_1的解释,q个质料可以在servlet的实C码中扑ֈ?br />3.对include的解?br />格式的,但是很不q,׃那个?org.apache.jasper.compiler.Parser"的h
在数lJspUtil.ValidAttribute[]忘记加了一个参敎ͼencoding,因此D不支
持这U方式。你完全可以~译源代码,加上对encoding的支?br />ȝQ?br />如果你在NT底下Q最单的Ҏ是ƺ骗java,不加MEncoding变量Q?br /><html>
你好<%=request.getParameter("value")%>
</html>
http://localhost/test/test.jsp?value
=?br />l果:你好?br />但这U方法局限性较大,比如对上传的文章分段Q这L做法是死定的Q最好的
解决Ҏ是用q种ҎQ?br /><%@ page contentType="text/html;charset=gb2312" %>
<html>
你好<%=new String(request.getParameter("value").getBytes("8859_1"),"gb2312")%>
</html>
<select name="account.accountId" >
<OPTION value="<%=account.getAccountId()%>">我的日志</OPTION>
<OPTION value="">所有日?lt;/OPTION>
<OPTION <%=s%> value="<%=a.getAccountId()%>"><%=a.getAccountName()%></OPTION>
</select>
]]>
java是一门面向对象的语言,在代码里,_略的讲一个对象的体现是一个类(class)的实?也可以说是一个JavaBean.在一个实际工E中,像这L对象或实例会存在很多,q且每个对象的状?作用范围,以及它们之间的关p?在Spring中ؓ依赖)是很复杂?所以要理它们也是很大的开销.而在spring?对与它们的管理就是容器管?你可以看作容器就是这些bean的集? 理的方面主要有bean的创?周期(作用?和初始属?注入),以及bean之间怺依赖的关pȝ.用比较专业的话就?-----理对象对其q行实例化、配|以及组?
Spring IoC 容器
?. 容器的运?
在Spring包的有两个很重要的东?org.springframework.beans?tt class="literal">org.springframework.context?q两个包是IOC的基?自然也是q行IOC容器的关?而其中关键的关键是分别在两个包里的BeanFactory?font face="Courier New">ApplicationContext,其中BeanFactory提供了配制框架及基本功能, ?/font>
ApplicationContext则是它的扩展,q个扩展是针对企业别的,当中加入很多了企业的支?功能得到了进一步增强,比如更易与Spring AOP集成、消息资源处?国际化处?、事件传递及各种不同应用层的context实现(如针对web应用的WebApplicartionContext).
1 . 实例化容?
在项目工E中用于实例化容器的cM般都是ApplicationContext以及他的扩展WebApplicationContext,当然BeanFactory也能?
在代码中一般是:
//1.
Resource resource = new FileSystemResource("beans.xml");BeanFactory factory = new XmlBeanFactory(resource);
//2.
ClassPathResource resource = new ClassPathResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
//3.
ApplicationContext context = new ClassPathXmlApplicationContext(
new String[]{"applicationContext.xml", "applicationContext-part2.xml"});
// of course, an ApplicationContext is just a BeanFactory
BeanFactory factory = (BeanFactory) context;
//4.ApplicationContext context = new FileSystemXmlApplicationContext("src\\beans.xml");
实际的项目中,上述的实例化Ҏ一般都是用于非Web工程(c/s)或者测试代码中而在web工程内一般用的是ApplicationContext,实例化它只是在web配置文g(web.xml)里写入配|信?
2. 容器的?
一般这是在代码U创ZIOC容器?是上述?1)),或者是获得了容器的"引用"后用(q里其实是beanFactory和ApplicationContext的实现类的引??);
上面六点,都是在BeanFactory中的基本和一些简单的用法,但在其扩展后了的ApplicationContext中加入了企业U的功能,比如国际?资源讉K{?q些我将在学习Spring
XML格式的元数据配置中学?
三?. 配置元数?br /> 我自q理解: 配置元数据的作用是Spring理Bean对象关系和资源文件的"规章制度",它是告诉IOC容器如何ȝl对象和对象之间的关pL怎样?
目前,Spring支持三种配置元数据格式:XML格式、Java属性文件格式或使用Spring公共API~程实现。很昄,XML是现在最方便和容易编写的配置元数?
在Spring的XMl配置元数据格式ؓ:
到此,理解了什么是Spring,以及它在工程中的基本框架,下面着重学习的是它的依赖注入和AOP技术的q用,学习是如何在XML元数据中q行配置.