马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
由于这些智能化家电的市场需求没有预期的高,Sun放弃了该项计划。就在Oak几近失败之时,随着互联网的发展,Sun看到了Oak在计算机网络上的广阔应用前景,于是改造了Oak,办理|中文申明:本文为作者原创,作者接洽地点为:josserchai@yahoo.com。因为Java编程中的中文成绩是一个陈词滥调的成绩,在浏览了很多关于Java中文成绩办理办法以后,分离作者的编程理论,我发明已往谈的很多办法都不克不及明晰地申明成绩及办理成绩,特别是跨平台时的中文成绩。因而我给出此篇文章,内容包含对把持台运转的class、Servelets、JSP及EJB类中的中文成绩我分析和倡议办理举措。但愿人人指教。
Abstract:本文深切剖析了Java程序计划中Java编译器对java源文件和JVM对class类文件的编码/解码历程,经由过程此历程的剖析透视出了Java编程中中文成绩发生的基本缘故原由,最初给出了倡议的最优化的办理Java中文成绩的办法。
1、中文成绩的来历
盘算机最后的操纵体系撑持的编码是单字节的字符编码,因而,在盘算机中统统处置程序最后都是以单字节编码的英文为准举行处置。跟着盘算机的开展,为了顺应天下别的平易近族的言语(固然包含我们的汉字),人们提出了UNICODE编码,它接纳双字节编码,兼容英笔墨符和别的平易近族的双字节字符编码,以是,今朝,年夜多半国际性的软件外部均接纳UNICODE编码,在软件运转时,它取得当地撑持体系(多半工夫是操纵体系)默许撑持的编码格局,然后再将软件外部的UNICODE转化为当地体系默许撑持的格局显现出来。Java的JDK和JVM便是云云,我这里说的JDK是指国际版的JDK,我们年夜多半程序员利用的是国际化的JDK版本,以下一切的JDK均指国际化的JDK版本。我们的汉字是双字节编码言语,为了能让盘算机处置中文,我们本人制订的gb2312、GBK、GBK2K等尺度以顺应盘算机处置的需求。以是,年夜部分的操纵体系为了顺应我们处置中文的需求,均定制有中文操纵体系,它们接纳的是GBK,GB2312编码格局以准确显现我们的汉字。如:中文Win2K默许接纳的是GBK编码显现,在中文WIN2k中保留文件时默许接纳的保留文件的编码格局也是GBK的,即,一切在中文WIN2K中保留的文件它的外部编码默许均接纳GBK编码,注重:GBK是在GB2312基本上扩大来的。
因为Java言语外部接纳UNICODE编码,以是在JAVA程序运转时,就存在着一个从UNICODE编码和对应的操纵体系及扫瞄器撑持的编码格局转换输出、输入的成绩,这个转换历程有着一系列的步骤,假如个中任何一步堕落,则显现出来的汉字就会出是乱码,这就是我们罕见的JAVA中文成绩。
同时,Java是一个跨平台的编程言语,也即我们编写的程序不但能在中文windows上运转,也能在中文Linux等体系上运转,同时也请求能在英文等体系上运转(我们常常看到有人把在中文win2k上编写的JAVA程序,移植到英文Linux上运转)。这类移植操纵也会带来中文成绩。
另有,有人利用英文的操纵体系和英文的IE等扫瞄器,来运转带中笔墨符的程序和扫瞄中文网页,它们自己就不撑持中文,也会带来中文成绩。
几近一切的扫瞄器默许在传送参数时都是以UTF-8编码格局来传送,而不是按中文编码传送,以是,传送中文参数时也会有成绩,从而带来乱码征象。
总之,以上几个方面是JAVA中的中文成绩的次要来历,我们把以上缘故原由酿成的程序不克不及准确运转而发生的成绩称作:JAVA中文成绩。
2、JAVA编码转换的具体历程
我们罕见的JAVA程序包含以下种别:
*间接在console上运转的类(包含可视化界面的类)
*JSP代码类(注:JSP是Servlets类的变型)
*Servelets类
*EJB类
*别的不成以间接运转的撑持类
这些类文件中,都有大概含有中笔墨符串,而且我们经常使用前三类JAVA程序和用户间接交互,用于输入和输出字符,如:我们在JSP和Servlet中失掉客户端送来的字符,这些字符也包含中笔墨符。不管这些JAVA类的感化怎样,这些JAVA程序的性命周期都是如许的:
*编程职员在必定的操纵体系上选择一个符合的编纂软件来完成源程序代码并以.java扩大名保留在操纵体系中,比方我们在中文win2k顶用记事本编纂一个java源程序;
*编程职员用JDK中的javac.exe来编译这些源代码,构成.class类(JSP文件是由容器挪用JDK来编译的);
*间接运转这些类或将这些类布署到WEB容器中往运转,并输入了局。
那末,在这些过程当中,JDK和JVM是怎样将这些文件怎样编码息争码并运转的呢?
这里,我们以中文win2k操纵体系为例申明JAVA类是怎样来编码和被解码的。
第一步,我们在中文win2k顶用编纂软件如记事本编写一个Java源程叙文件(包含以上五类JAVA程序),程叙文件在保留时默许接纳了操纵体系默许撑持GBK编码格局(操纵体系默许撑持的格局为file.encoding格局)构成了一个.java文件,也即,java程序在被编译前,我们的JAVA源程叙文件是接纳操纵体系默许撑持的file.encoding编码格局保留的,java源程序中含有中文信息字符和英文程序代码;要检察体系的file.encoding参数,能够用以下代码:
publicclassShowSystemDefaultEncoding{
publicstaticvoidmain(String[]args){
Stringencoding=System.getProperty("file.encoding");
System.out.println(encoding);
}}
第二步,我们用JDK的javac.exe文件编译我们的Java源程序,因为JDK是国际版的,在编译的时分,假如我们没有效-encoding参数指定我们的JAVA源程序的编码格局,则javac.exe起首取得我们操纵体系默许接纳的编码格局,也即在编译java程序时,若我们不指定源程叙文件的编码格局,JDK起首取得操纵体系的file.encoding参数(它保留的就是操纵体系默许的编码格局,如WIN2k,它的值为GBK),然后JDK就把我们的java源程序从file.encoding编码格局转化为JAVA外部默许的UNICODE格局放进内存中。然后,javac把转换后的unicode格局的文件举行编译成.class类文件,此时.class文件是UNICODE编码的,它暂放在内存中,紧接着,JDK将此以UNICODE编码的编译后的class文件保留到我们的操纵体系中构成我们见到的.class文件。对我们来讲,我们终极取得的.class文件是内容以UNICODE编码格局保留的类文件,它外部包括我们源程序中的中笔墨符串,只不外此时它己经过file.encoding格局转化为UNICODE格局了。
这一步中,关于JSP源程叙文件是分歧的,关于JSP,这个历程是如许的:即WEB容器挪用JSP编译器,JSP编译器先检察JSP文件中是不是设置有文件编码格局,假如JSP文件中没有设置JSP文件的编码格局,则JSP编译器挪用JDK先把JSP文件用JVM默许的字符编码格局(也即WEB容器地点的操纵体系的默许的file.encoding)转化为一时的Servlet类,然后再把它编译成UNICODE格局的class类,并保留在一时文件夹中。如:在中文win2k上,WEB容器就把JSP文件从GBK编码格局转化为UNICODE格局,然后编译成一时保留的Servlet类,以呼应用户的哀求。
第三步,运转第二步编译出来的类,分为三种情形:
A、间接在console上运转的类
B、EJB类和不成以间接运转的撑持类(如JavaBean类)
C、JSP代码和Servlet类
D、JAVA程序和数据库之间
上面我们分这四种情形来看。
A、间接在console上运转的类
这类情形,运转该类起首必要JVM撑持,即操纵体系中必需安装有JRE。运转历程是如许的:起首java启动JVM,此时JVM读出操纵体系中保留的class文件并把内容读进内存中,此时内存中为UNICODE格局的class类,然后JVM运转它,假如此时此类必要吸收用户输出,则类会默许用file.encoding编码格局对用户输出的串举行编码并转化为unicode保留进内存(用户能够设置输出流的编码格局)。程序运转后,发生的字符串(UNICODE编码的)再回交给JVM,最初JRE把此字符串再转化为file.encoding格局(用户能够设置输入流的编码格局)传送给操纵体系显现接口并输入到界面上。
关于这类间接在console上运转的类,它的转化历程可用加倍明白的暗示出来:
以上每步的转化都必要准确的编码格局转化,才干终极不呈现乱码征象。
B、EJB类和不成以间接运转的撑持类(如JavaBean类)
因为EJB类和不成以间接运转的撑持类,它们一样平常不与用户间接交互输出和输入,它们经常与别的的类举行交互输出和输入,以是它们在第二步被编译后,就构成了内容是UNICODE编码的类保留在操纵体系中了,今后只需它与别的的类之间的交互在参数传送过程当中没有丧失,则它就会准确的运转。
这类EJB类和不成以间接运转的撑持类,它的转化历程可用加倍明白的暗示出来:
C、JSP代码和Servlet类
经由第二步后,JSP文件也被转化为Servlets类文件,只不外它不像尺度的Servlets一校存在于classes目次中,它存在于WEB容器的一时目次中,故这一步中我们也把它做为Servlets来看。
关于Servlets,客户端哀求它时,WEB容器挪用它的JVM来运转Servlet,起首,JVM把Servlet的class类从体系中读出并装进内存中,内存中是以UNICODE编码的Servlet类的代码,然后JVM在内存中运转该Servlet类,假如Servlet在运转的过程当中,必要承受从客户端传来的字符如:表单输出的值和URL中传进的值,此时假如程序中没有设定承受参数时接纳的编码格局,则WEB容器会默许接纳ISO-8859-1编码格局来承受传进的值并在JVM直达化为UNICODE格局的保留在WEB容器的内存中。Servlet运转后天生输入,输入的字符串是UNICODE格局的,紧接着,容器将Servlet运转发生的UNICODE格局的串(如html语法,用户输入的串等)间接发送到客户端扫瞄器上并输入给用户,假如此时指定了发送时输入的编码格局,则按指定的编码格局输入到扫瞄器上,假如没有指定,则默许按ISO-8859-1编码发送到客户的扫瞄器上。这类JSP代码和Servlet类,它的转化历程可用加倍明白地暗示出来:
D、Java程序和数据库之间
关于几近一切数据库的JDBC驱动程序,默许的在JAVA程序和数据库之间传送数据都是以ISO-8859-1为默许编码格局的,以是,我们的程序在向数据库内存储包括中文的数据时,JDBC起首是把程序外部的UNICODE编码格局的数据转化为ISO-8859-1的格局,然后传送到数据库中,在数据库保留数据时,它默许即以ISO-8859-1保留,以是,这是为何我们经常在数据库中读出的中文数据是乱码。
关于JAVA程序和数据库之间的数据传送,我们能够用明晰地暗示出来
3、剖析罕见的JAVA中文成绩几个必需分明的准绳
起首,经由下面的具体剖析,我们能够明晰地看到,任何JAVA程序的性命期中,其编码转换的关头历程是在于:最后编译成class文件的转码和终极向用户输入的转码历程。
其次,我们必需懂得JAVA在编译时撑持的、经常使用的编码格局有以下几种:
*ISO-8859-1,8-bit,同8859_1,ISO-8859-1,ISO_8859_1等编码
*Cp1252,美国英语编码,同ANSI尺度编码
*UTF-8,同unicode编码
*GB2312,同gb2312-80,gb2312-1980等编码
*GBK,同MS936,它是gb2312的扩大
及别的的编码,如韩文、日文、繁体中文等。同时,我们要注重这些编码间的兼容关系统以下:
unicode和UTF-8编码是逐一对应的干系。GB2312能够以为是GBK的子集,即GBK编码是在gb2312上扩大来的。同时,GBK编码包括了20902个汉字,编码局限为:0x8140-0xfefe,一切的字符能够逐一对应到UNICODE2.0中来。
再次,关于放在操纵体系中的.java源程叙文件,在编译时,我们能够指定它内容的编码格局,详细来讲用-encoding来指定。注重:假如源程序中含有中笔墨符,而你用-encoding指定为别的的编码字符,明显是要堕落的。用-encoding指定源文件的编码体例为GBK或gb2312,不管我们在甚么体系上编译含有中笔墨符的JAVA源程序都不会有成绩,它城市准确地将中文转化为UNICODE存储在class文件中。
然后,我们必需分明,几近一切的WEB容器在其外部默许的字符编码格局都是以ISO-8859-1为默许值的,同时,几近一切的扫瞄器在传送参数时都是默许以UTF-8的体例来传送参数的。以是,固然我们的Java源文件在收支口的中央指定了准确的编码体例,但其在容器外部运转时仍是以ISO-8859-1来处置的。
JAVA是一种可以撰写跨平台应用软件的面向对象的程序设计语言,由升阳(SunMicrosystems)公司的詹姆斯·高斯林(JamesGosling)等人于1990年代初开发。 |