`

java编码转换的详细过程及中文处理相关问题

阅读更多
  1. 常见的JAVA程序包括以下类别:
  2. *直接在console上运行的类(包括可视化界面的类)
  3. *JSP代码类(注:JSP是Servlets类的变型)
  4. *Servelets类
  5. *EJB类
  6. *其它不可以直接运行的支持类
  7. 这些类文件中,都有可能含有中文字符串,并且常用前三类JAVA程序和用户直接交互,用于输出和输入字符,如:在JSP和Servlet中得到客户端送来的字符,这些字符也包括中文字符。无论这些JAVA类的作用如何,这些JAVA程序的生命周期都是这样的:
  8. *编程人员在一定的操作系统上选择一个合适的编辑软件来实现源程序代码并以.java扩展名保存在操作系统中,例如我们在中文win2k中用记事本编辑一个java源程序;
  9. *编程人员用JDK中的javac.exe来编译这些源代码,形成.class类(JSP文件是由容器调用JDK来编译的);
  10. *直接运行这些类或将这些类布署到WEB容器中去运行,并输出结果。
  11. 那么,在这些过程中,JDK和JVM是如何将这些文件如何编码和解码并运行的呢?
  12. 这里,以中文win2k操作系统为例说明JAVA类是如何来编码和被解码的。
  13. 第一步,我们在中文win2k中用编辑软件如记事本编写一个Java源程序文件(包括以上五类JAVA程序),程序文件在保存时默认采用了操作系统默认支持GBK编码格式(操作系统默认支持的格式为file.encoding格式)形成了一个.java文件,也即,java程序在被编译前,我们的JAVA源程序文件是采用操作系统默认支持的file.encoding编码格式保存的,java源程序中含有中文信息字符和英文程序代码;要查看系统的file.encoding参数,可以用以下代码:
  14.   publicclassShowSystemDefaultEncoding{
  15.   publicstaticvoidmain(String[]args){
  16.   Stringencoding=System.getProperty("file.encoding");
  17.   System.out.println(encoding);
  18.   }}
  19. 第二步,我们用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格式了。
  20. 这一步中,对于JSP源程序文件是不同的,对于JSP,这个过程是这样的:即WEB容器调用JSP编译器,JSP编译器先查看JSP文件中是否设置有文件编码格式,如果JSP文件中没有设置JSP文件的编码格式,则JSP编译器调用JDK先把JSP文件用JVM默认的字符编码格式(也即WEB容器所在的操作系统的默认的file.encoding)转化为临时的Servlet类,然后再把它编译成UNICODE格式的class类,并保存在临时文件夹中。如:在中文win2k上,WEB容器就把JSP文件从GBK编码格式转化为UNICODE格式,然后编译成临时保存的Servlet类,以响应用户的请求。
  21. 第三步,运行第二步编译出来的类,分为三种情况:
  22. A、直接在console上运行的类
  23. B、EJB类和不可以直接运行的支持类(如JavaBean类)
  24. C、JSP代码和Servlet类
  25. D、JAVA程序和数据库之间
  26. 下面分这四种情况来看。
  27. A、直接在console上运行的类
  28. 这种情况,运行该类首先需要JVM支持,即操作系统中必须安装有JRE。运行过程是这样的:首先java启动JVM,此时JVM读出操作系统中保存的class文件并把内容读入内存中,此时内存中为UNICODE格式的class类,然后JVM运行它,如果此时此类需要接收用户输入,则类会默认用file.encoding编码格式对用户输入的串进行编码并转化为unicode保存入内存(用户可以设置输入流的编码格式)。程序运行后,产生的字符串(UNICODE编码的)再回交给JVM,最后JRE把此字符串再转化为file.encoding格式(用户可以设置输出流的编码格式)传递给操作系统显示接口并输出到界面上。
  29. 以上每一步的转化都需要正确的编码格式转化,才能最终不出现乱码现象。
  30. B、EJB类和不可以直接运行的支持类(如JavaBean类)
  31. 由于EJB类和不可以直接运行的支持类,它们一般不与用户直接交互输入和输出,它们常常与其它的类进行交互输入和输出,所以它们在第二步被编译后,就形成了内容是UNICODE编码的类保存在操作系统中了,以后只要它与其它的类之间的交互在参数传递过程中没有丢失,则它就会正确的运行。
  32. C、JSP代码和Servlet类
  33. 经过第二步后,JSP文件也被转化为Servlets类文件,只不过它不像标准的Servlets一校存在于classes目录中,它存在于WEB容器的临时目录中,故这一步中我们也把它做为Servlets来看。
  34. 对于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编码发送到客户的浏览器上。
  35. D、Java程序和数据库之间
  36. 对于几乎所有数据库的JDBC驱动程序,默认的在JAVA程序和数据库之间传递数据都是以ISO-8859-1为默认编码格式的,所以,我们的程序在向数据库内存储包含中文的数据时,JDBC首先是把程序内部的UNICODE编码格式的数据转化为ISO-8859-1的格式,然后传递到数据库中,在数据库保存数据时,它默认即以ISO-8859-1保存,所以,这是为什么我们常常在数据库中读出的中文数据是乱码。
  37. 3、分析常见的JAVA中文问题几个必须清楚的原则
  38. 首先,经过上面的详细分析,我们可以清晰地看到,任何JAVA程序的生命期中,其编码转换的关键过程是在于:最初编译成class文件的转码和最终向用户输出的转码过程。
  39. 其次,我们必须了解JAVA在编译时支持的、常用的编码格式有以下几种:
  40. *ISO-8859-1,8-bit,同8859_1,ISO-8859-1,ISO_8859_1等编码
  41. *Cp1252,美国英语编码,同ANSI标准编码
  42. *UTF-8,同unicode编码
  43. *GB2312,同gb2312-80,gb2312-1980等编码
  44. *GBK,同MS936,它是gb2312的扩充
  45. 及其它的编码,如韩文、日文、繁体中文等。同时,我们要注意这些编码间的兼容关体系如下:
  46. unicode和UTF-8编码是一一对应的关系。GB2312可以认为是GBK的子集,即GBK编码是在gb2312上扩展来的。同时,GBK编码包含了20902个汉字,编码范围为:0x8140-0xfefe,所有的字符可以一一对应到UNICODE2.0中来。
  47. 再次,对于放在操作系统中的.java源程序文件,在编译时,我们可以指定它内容的编码格式,具体来说用-encoding来指定。注意:如果源程序中含有中文字符,而你用-encoding指定为其它的编码字符,显然是要出错的。用-encoding指定源文件的编码方式为GBK或gb2312,无论我们在什么系统上编译含有中文字符的JAVA源程序都不会有问题,它都会正确地将中文转化为UNICODE存储在class文件中。
  48. 然后,我们必须清楚,几乎所有的WEB容器在其内部默认的字符编码格式都是以ISO-8859-1为默认值的,同时,几乎所有的浏览器在传递参数时都是默认以UTF-8的方式来传递参数的。所以,虽然我们的Java源文件在出入口的地方指定了正确的编码方式,但其在容器内部运行时还是以ISO-8859-1来处理的。
  49. 4、中文问题的分类及其建议最优解决办法
  50. 了解以上JAVA处理文件的原理之后,我们就可以提出了一套建议最优的解决汉字问题的办法。
  51. 我们的目标是:我们在中文系统中编辑的含有中文字符串或进行中文处理的JAVA源程序经编译后可以移值到任何其它的操作系统中正确运行,或拿到其它操作系统中编译后能正确运行,能正确地传递中文和英文参数,能正确地和数据库交流中英文字符串。
  52. 我们的具体思路是:在JAVA程序转码的入口和出口及JAVA程序同用户有输入输出转换的地方限制编码方法使之正确即可。
  53. 具体解决办法如下:
  54. 1、针对直接在console上运行的类
  55. 对于这种情况,我们建议在程序编写时,如果需要从用户端接收用户的可能含有中文的输入或含有中文的输出,程序中应该采用字符流来处理输入和输出,具体来说,应用以下面向字符型节点流类型:
  56. 对文件:FileReader,FileWrieter
  57. 其字节型节点流类型为:FileInputStream,FileOutputStream
  58. 对内存(数组):CharArrayReader,CharArrayWriter
  59. 其字节型节点流类型为:ByteArrayInputStream,ByteArrayOutputStream
  60. 对内存(字符串):StringReader,StringWriter
  61. 对管道:PipedReader,PipedWriter
  62. 其字节型节点流类型为:PipedInputStream,PipedOutputStream
  63. 同时,应该用以下面向字符型处理流来处理输入和输出:
  64. BufferedWriter,BufferedReader
  65. 其字节型的处理流为:BufferedInputeStream,BufferedOutputStream
  66. InputStreamReader,OutputStreamWriter
  67. 其字节型的处理流为:DataInputStream,DataOutputStream
  68. 其中InputStreamReader和InputStreamWriter用于将字节流按照指定的字符编码集转换到字符流,如:
  69. InputStreamReaderin=newInputStreamReader(System.in"GB2312");
  70. OutputStreamWriterout=newOutputStreamWriter(System.out"GB2312");
  71. 例如:采用如下的示例JAVA编码就达到了要求:
  72. //Read.java
  73. importjava.io.*;
  74. publicclassRead{
  75. publicstaticvoidmain(String[]args)throwsIOException{
  76. Stringstr="\n中文测试,这是内部硬编码的串"+"\ntestenglishcharacter";
  77. Stringstrin="";
  78. BufferedReaderstdin=newBufferedReader(newInputStreamReader(System.in,"gb2312"));//设置输入接口按中文编码
  79. BufferedWriterstdout=newBufferedWriter(newOutputStreamWriter(System.out,"gb2312"));//设置输出接口按中文编码
  80. stdout.write("请输入:");
  81. stdout.flush();
  82. strin=stdin.readLine();
  83. stdout.write("这是从用户输入的串:"+strin);
  84. stdout.write(str);
  85. stdout.flush();
  86. }}
  87. 同时,在编译程序时,我们用以下方式来进行:
  88. javac-encodinggb2312Read.java
  89. 2、针对EJB类和不可以直接运行的支持类(如JavaBean类)
  90. 由于这种类它们本身被其它的类调用,不直接与用户交互,故对这种类来说,我们的建议的处理方式是内部程序中应该采用字符流来处理程序内部的中文字符串(具体如上面一节中一样),同时,在编译类时用-encodinggb2312参数指示源文件是中文格式编码的即可。
  91. 3、针对Servlet类
  92. 针对Servlet,我们建议用以下方法:
  93. 在编译Servlet类的源程序时,用-encoding指定编码为GBK或GB2312,且在向用户输出时的编码部分用response对象的setContentType("text/html;charset=GBK");或gb2312来设置输出编码格式,同样在接收用户输入时,我们用request.setCharacterEncoding("GB2312");这样无论我们的servlet类移植到什么操作系统中,只有客户端的浏览器支持中文显示,就可以正确显示。如下是一个正确的示例:
  94. //HelloWorld.java
  95. packagehello;
  96. importjava.io.*;
  97. importjavax.servlet.*;
  98. importjavax.servlet.http.*;
  99. publicclassHelloWorldextendsHttpServlet
  100. {
  101. publicvoidinit()throwsServletException{}
  102. publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException,ServletException
  103. {
  104. request.setCharacterEncoding("GB2312");//设置输入编码格式
  105. response.setContentType("text/html;charset=GB2312");//设置输出编码格式
  106. PrintWriterout=response.getWriter();//建议使用PrintWriter输出
  107. out.println("HelloWorld!ThisiscreatedbyServlet!测试中文!");
  108. }
  109. publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException,ServletException
  110. {
  111. request.setCharacterEncoding("GB2312");//设置输入编码格式
  112. response.setContentType("text/html;charset=GB2312");//设置输出编码格式
  113. Stringname=request.getParameter("name");
  114. Stringid=request.getParameter("id");
  115. if(name==null)name="";
  116. if(id==null)id="";
  117. PrintWriterout=response.getWriter();//建议使用PrintWriter输出
  118. out.println("你传入的中文字串是:"+name);
  119. out.println("你输入的id是:"+id);
  120. }
  121. publicvoiddestroy(){}
  122. 请用javac-encodinggb2312HelloWorld.java来编译此程序。
  123. 4、JAVA程序和数据库之间
  124. 为避免JAVA程序和数据库之间数据传递出现乱码现象,我们建议采用以下最优方法来处理:
  125. 1、对于JAVA程序的处理方法按我们指定的方法处理。
  126. 2、把数据库默认支持的编码格式改为GBK或GB2312的。
  127. 如:在mysql中,我们可以在配置文件my.ini中加入以下语句实现:
  128. 在[mysqld]区增加:
  129. default-character-set=gbk
  130. 并增加:
  131. [client]
  132. default-character-set=gbk
  133. 在SQLServer2K中,我们可以将数据库默认的语言设置为SimplifiedChinese来达到目的。
  134. 5、针对JSP代码
  135. 由于JSP是在运行时,由WEB容器进行动态编译的,如果我们没有指定JSP源文件的编码格式,则JSP编译器会获得服务器操作系统的file.encoding值来对JSP文件编译的,它在移植时最容易出问题,如在中文win2k中可以很好运行的jsp文件拿到英文linux中就不行,尽管客户端都是一样的,那是因为容器在编译JSP文件时获取的操作系统的编码不同造成的(在中文wink中的file.encoding和在英文Linux中file.encoding是不同的,且英文Linux的file.encoding对中文不支持,所以编译出来的JSP类就会有问题)。网络上讨论的大多数是此类问题,多是因为JSP文件移植平台时不能正确显示的问题,对于这类问题,我们了解了JAVA中程序编码转换的原理,解决起来就容易多了。我们建议的解决办法如下:
  136. 1、我们要保证JSP向客户端输出时是采用中文编码方式输出的,即无论如何我们首先在我们的JSP源代编中加入以下一行:
  137. <%@pagecontentType=”text/html;charset=gb2312″%>
  138. 2、为了让JSP能正确获得传入的参数,我们在JSP源文件头加入下面一句:
  139. <%request.setCharacterEncoding(”GB2312″);%>
  140. 3、为了让JSP编译器能正确地解码我们的含有中文字符的JSP文件,我们需要在JSP源文件中指定我们的JSP源文件的编码格式,具体来说,我们在JSP源文件头上加入下面的一句即可:
  141. 这是JSP规范2.0新增加的指令。
  142. 我们建议使用此方法来解JSP文件中的中文问题,下面的代码是一个正确做法的JSP文件的测试程序:
  143. <%@pagepageEncoding=”GB2312″%>
  144. <%@pagecontentType=”text/html;
  145. charset=gb2312″%>
  146. <%request.setCharacterEncoding(”GB2312″);
  147. %>
  148. <%
  149. Stringaction=request.getParameter(”ACTION”);
  150. Stringname=“”;
  151. Stringstr=“”;
  152. if(action!=null&&action.equals(”SENT”))
  153. {
  154. name=request.getParameter(”name”);
  155. str=request.getParameter(”str”);
  156. }
  157. %>
  158. <html>
  159. <head>
  160. <title></title>
  161. <Scriptlanguage=”JavaScript”>
  162. functionSubmit()
  163. {
  164. document.base.action=
  165. “?ACTION=SENT&str=传入的中文”;
  166. document.base.method=“POST”;
  167. document.base.submit();
  168. }
  169. </Script>
  170. </head>
  171. <bodybgcolor=”#FFFFFF”
  172. text=”#000000″topmargin=”5″>
  173. <formname=”base”method=
  174. “POST”target=”_self”>
  175. <inputtype=”text”name=”name”
  176. value=”"size=”30″>
  177. <ahref=“JavaScript:Submit()”>提交</a>
  178. </form>
  179. <%
  180. if(action!=null&&action.equals(”SENT”))
  181. {
  182. out.println(”<br>你输入的字符为:”+name);
  183. out.println(”<br>你通过URL传入的字符为:”+str);
  184. }
  185. %>
  186. </body>
  187. </html>
分享到:
评论

相关推荐

    java字符编码转换详细过程

    ### Java字符编码转换详细过程 #### 一、Java程序的生命周期与字符编码处理流程 Java程序的生命周期可以概括为三个主要阶段:编写源代码、编译源代码以及运行编译后的类文件。在这个过程中,涉及到多种字符编码的...

    java编码转换工具

    java编码转换工具

    Java文件编码转换源码

    在Java编程语言中,文件编码转换是一个常见的任务,特别是在处理多国语言或者处理不同系统间的文件传输时。本文将深入探讨如何使用Java实现文件编码的转换,主要关注GB2312、UTF-8这两种常见编码格式之间的转换。 ...

    java编码转换的详细过程.pdf

    Java 编码转换的详细过程 Java 编码转换是 Java 程序的生命周期中一个非常重要的过程。在 Java 程序的生命周期中,编程人员首先编写源程序代码,然后将其编译成.class 文件,最后将其运行在 JVM 中。在这个过程中,...

    java 文件编码转换

    标题"java 文件编码转换"指的是使用Java来解决文件编码问题,而描述中提到的"提供一个jar包和一个java文件"则暗示了我们可以通过这两个文件实现这个功能。 首先,`chardet.jar`可能是一个字符集检测库,用于自动...

    JAVA 转换字符编码工具

    `JAVA 转换字符编码工具`可能是一个用于处理字符编码转换的Java程序,旨在帮助开发者解决不同编码格式之间转换的问题。这篇博文链接(虽然没有提供具体内容)可能详细介绍了这个工具的实现原理和使用方法。 在Java...

    java字符串编码转换

    本文介绍了Java字符串编码转换的基础知识,并结合Web环境中的具体应用场景进行了详细的说明。在处理不同编码格式的数据时,正确地使用编码转换方法对于确保数据的一致性和准确性非常重要。开发者应当熟悉各种编码...

    java编码格式转换

    #### 常见的编码转换错误及处理 1. **从Unicode转换为ISO-8859-1导致的信息丢失**: - 当尝试将包含非ASCII字符的Unicode字符串转换为ISO-8859-1编码时,所有非ASCII字符都会被替换为`?`或者丢失。 - 解决方法:...

    java中文乱码解决之道(4)java编码转换过程Java

    在Java编程语言中,中文乱码问题是一个常见的挑战,特别...以上内容涵盖了Java编码转换的基本原理和处理乱码问题的关键点,希望对Java开发者有所帮助。在实际工作中,遇到具体问题时,还需结合实际情况进行分析和调试。

    java文件的编码转换

    在IT行业中,编码转换是一个常见的问题,特别是在处理不同来源或平台的文件时。Java作为一种广泛使用的编程语言,处理文件编码转换也是其能力之一。本文将深入探讨“Java文件的编码转换”这一主题,以及如何利用Java...

    java字符串的各种编码转换

    根据提供的文件信息,本文将详细解释Java中字符串的不同编码转换方法及原理,并深入探讨每种编码格式的特点。 ### Java字符串的编码转换 在Java中,处理不同字符集之间的字符串转换是一项常见任务。尤其是在处理...

    Java字符编码转换过程说明

    Java字符编码转换是Java开发中一个重要的...总的来说,理解Java中的字符编码转换过程至关重要,这有助于在处理多语言和跨平台项目时避免数据丢失或乱码问题。开发者应始终关注编码的正确设置,并在必要时进行手动转换。

    java 中文Unicode转换

    总的来说,Java提供了丰富的API来处理Unicode编码,无论是转换中文字符还是从Unicode码点恢复字符,都可以轻松实现。在处理多语言文本时,理解和熟练运用Unicode编码是至关重要的。通过上述方法,你可以有效地在Java...

    java批量转换文件编码

    本话题主要关注如何使用Java进行批量文件编码转换,特别是从一种编码(如GBK)转换到另一种编码(如UTF-8)。以下是对这个主题的详细阐述: 首先,我们需要理解什么是文件编码。文件编码是存储和显示文本内容的规则...

    文件编码转换工具java

    综上所述,这个“文件编码转换工具java”是一个便捷、跨平台的工具,提供了源代码以供扩展和学习,能够处理多国语言的编码问题,并且支持批量转换,极大地提升了文件管理效率,特别适合开发者和需要处理多语言文件的...

    java编码转换介绍文档

    Java编码转换是一个重要的主题,特别是在处理跨平台和国际化应用时。Java编程中,编码问题时常出现,例如在处理中文字符时可能出现乱码。为了解决这些问题,Java提供了一个名为`native2ascii`的工具,该工具能够帮助...

    JAVA编码转换一个类 源代码

    编码转换的类 含源代码, 适合编码转换时候使用 默认转换为UTF-8 可以转换成别的

    java文件字符编码检测和转换

    附件中:FileCharsetConverter.java 此文件可以实现两个编码的相互转换 FileCharsetConverter.convert( "gbk/DispatcherHandler.java", "GBK", "UTF-8", new FilenameFilter() { public boolean accept(File...

    Java源码编码转换器 v2.0 GBK TO UTF8

    Java源码编码转换器v2.0是一款专用于解决Java源码编码问题的工具,它主要功能是将GBK编码的Java文件转换成UTF-8编码,以解决由于编码不匹配导致的乱码问题。该工具在之前的版本基础上进行了优化,修复了UTF-8转换后...

    java_各种编码转换源代码

    在Java编程语言中,编码转换是一项重要的任务,特别是在处理不同来源的数据时,如读取文本文件、网络数据传输或数据库交互。...通过深入研究和实践,可以增强对Java编码转换机制的理解,提升软件质量。

Global site tag (gtag.js) - Google Analytics