工作小驛

          Ninja!

          BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
            103 Posts :: 0 Stories :: 36 Comments :: 0 Trackbacks

          4、中文問(wèn)題的分類及其建議最優(yōu)解決辦法

              了解以上JAVA處理文件的原理之后,我們就可以提出了一套建議最優(yōu)的解決漢字問(wèn)題的辦法。
                                                                                                
              我們的目標(biāo)是:我們?cè)谥形南到y(tǒng)中編輯的含有中文字符串或進(jìn)行中文處理的JAVA源程序經(jīng)編譯后可以移值到任何其它的操作系統(tǒng)中正確運(yùn)行,或拿到其它操作系統(tǒng)中編譯后能正確運(yùn)行,能正確地傳遞中文和英文參數(shù),能正確地和數(shù)據(jù)庫(kù)交流中英文字符串。
              我們的具體思路是:在JAVA程序轉(zhuǎn)碼的入口和出口及JAVA程序同用戶有輸入輸出轉(zhuǎn)換的地方限制編碼方法使之正確即可。

              具體解決辦法如下:

              1、 針對(duì)直接在console上運(yùn)行的類
              對(duì)于這種情況,我們建議在程序編寫時(shí),如果需要從用戶端接收用戶的可能含有中文的輸入或含有中文的輸出,程序中應(yīng)該采用字符流來(lái)處理輸入和輸出,具體來(lái)說(shuō),應(yīng)用以下面向字符型節(jié)點(diǎn)流類型:

              對(duì)文件:FileReader,F(xiàn)ileWrieter
              其字節(jié)型節(jié)點(diǎn)流類型為:FileInputStream,F(xiàn)ileOutputStream

              對(duì)內(nèi)存(數(shù)組):CharArrayReader,CharArrayWriter
                  其字節(jié)型節(jié)點(diǎn)流類型為:ByteArrayInputStream,ByteArrayOutputStream

              對(duì)內(nèi)存(字符串):StringReader,StringWriter

              對(duì)管道:PipedReader,PipedWriter
                  其字節(jié)型節(jié)點(diǎn)流類型為:PipedInputStream,PipedOutputStream

              同時(shí),應(yīng)該用以下面向字符型處理流來(lái)處理輸入和輸出:
              BufferedWriter,BufferedReader
                  其字節(jié)型的處理流為:BufferedInputeStream,BufferedOutputStream

              InputStreamReader,OutputStreamWriter
              其字節(jié)型的處理流為:DataInputStream,DataOutputStream

              其中InputStreamReader和InputStreamWriter用于將字節(jié)流按照指定的字符編碼集轉(zhuǎn)換到字符流,如:
              InputStreamReader in = new InputStreamReader(System.in,"GB2312");
              OutputStreamWriter out = new OutputStreamWriter (System.out,"GB2312");

              例如:采用如下的示例JAVA編碼就達(dá)到了要求:

              //Read.java
              import java.io.*;
              public class Read {
              public static void main(String[] args) throws IOException {
                String str = "\n中文測(cè)試,這是內(nèi)部硬編碼的串"+"\ntest english character";
                String strin= "";
                BufferedReader stdin =
                  new BufferedReader(new InputStreamReader(System.in,"gb2312")); //設(shè)置輸入接口按中文編碼
                BufferedWriter stdout =
                  new BufferedWriter(new OutputStreamWriter(System.out,"gb2312")); //設(shè)置輸出接口按中文編碼

              stdout.write("請(qǐng)輸入:");
              stdout.flush();
              strin = stdin.readLine();
              stdout.write("這是從用戶輸入的串:"+strin);
              stdout.write(str);
              stdout.flush();
              }
          }
              同時(shí),在編譯程序時(shí),我們用以下方式來(lái)進(jìn)行:
              javac -encoding gb2312 Read.java
              其運(yùn)行結(jié)果如圖5所示:

              圖5



          2、針對(duì)EJB類和不可以直接運(yùn)行的支持類(如JavaBean類)

              由于這種類它們本身被其它的類調(diào)用,不直接與用戶交互,故對(duì)這種類來(lái)說(shuō),我們的建議的處理方式是內(nèi)部程序中應(yīng)該采用字符流來(lái)處理程序內(nèi)部的中文字符串(具體如上面一節(jié)中一樣),同時(shí),在編譯類時(shí)用-encoding gb2312參數(shù)指示源文件是中文格式編碼的即可。


              3、針對(duì)Servlet類

              針對(duì)Servlet,我們建議用以下方法:

              在編譯Servlet類的源程序時(shí),用-encoding指定編碼為GBK或GB2312,且在向用戶輸出時(shí)的編碼部分用response對(duì)象的setContentType("text/html;charset=GBK");或gb2312來(lái)設(shè)置輸出編碼格式,同樣在接收用戶輸入時(shí),我們用request.setCharacterEncoding("GB2312");

             這樣無(wú)論我們的servlet類移植到什么操作系統(tǒng)中,只有客戶端的瀏覽器支持中文顯示,就可以正確顯示。如下是一個(gè)正確的示例:

              //HelloWorld.java
              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"); //設(shè)置輸入編碼格式
              response.setContentType("text/html;charset=GB2312"); //設(shè)置輸出編碼格式
              PrintWriter out = response.getWriter(); //建議使用PrintWriter輸出
              out.println("<hr>");
              out.println("Hello World! This is created by Servlet!測(cè)試中文!");
              out.println("<hr>");
              }

              public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
              {
              request.setCharacterEncoding("GB2312"); //設(shè)置輸入編碼格式
              response.setContentType("text/html;charset=GB2312"); //設(shè)置輸出編碼格式
              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() { }
              }
                  請(qǐng)用javac -encoding gb2312 HelloWorld.java來(lái)編譯此程序。
                  測(cè)試此Servlet的程序如下所示:

              <%@page contentType="text/html; charset=gb2312"%>
              <%
               request.setCharacterEncoding("GB2312");
              %>
              <html><head><title></title>
              <Script language="JavaScript">
              function Submit() {
              //通過(guò)URL傳遞中文字符串值給Servlet
              document.base.action = "/HelloWorld?name=中文";
              document.base.method = "POST";
              document.base.submit();
              }
              </Script>
              </head>

           <body bgcolor="#FFFFFF" text="#000000" topmargin="5">
              <form name="base" method = "POST" target="_self">
              <input name="id" type="text" value="" size="30">
              <a href = "JavaScript:Submit()">傳給Servlet</a>
              </form></body></html>

              其運(yùn)行結(jié)果如圖6所示:

              圖6
              4、 JAVA程序和數(shù)據(jù)庫(kù)之間

              為避免JAVA程序和數(shù)據(jù)庫(kù)之間數(shù)據(jù)傳遞出現(xiàn)亂碼現(xiàn)象,我們建議采用以下最優(yōu)方法來(lái)處理:
              1、對(duì)于JAVA程序的處理方法按我們指定的方法處理。
              2、把數(shù)據(jù)庫(kù)默認(rèn)支持的編碼格式改為GBK或GB2312的。

              如:在mysql中,我們可以在配置文件my.ini中加入以下語(yǔ)句實(shí)現(xiàn):
              在[mysqld]區(qū)增加:
              default-character-set=gbk
              并增加:
              [client]
              default-character-set=gbk
              在SQL Server2K中,我們可以將數(shù)據(jù)庫(kù)默認(rèn)的語(yǔ)言設(shè)置為Simplified Chinese來(lái)達(dá)到目的。

              5、 針對(duì)JSP代碼

              由于JSP是在運(yùn)行時(shí),由WEB容器進(jìn)行動(dòng)態(tài)編譯的,如果我們沒(méi)有指定JSP源文件的編碼格式,則JSP編譯器會(huì)獲得服務(wù)器操作系統(tǒng)的file.encoding值來(lái)對(duì)JSP文件編譯的,它在移植時(shí)最容易出問(wèn)題,如在中文win2k中可以很好運(yùn)行的jsp文件拿到英文linux中就不行,盡管客戶端都是一樣的,那是因?yàn)槿萜髟诰幾gJSP文件時(shí)獲取的操作系統(tǒng)的編碼不同造成的(在中文wink中的file.encoding和在英文Linux中file.encoding是不同的,且英文Linux的file.encoding對(duì)中文不支持,所以編譯出來(lái)的JSP類就會(huì)有問(wèn)題)。網(wǎng)絡(luò)上討論的大多數(shù)是此類問(wèn)題,多是因?yàn)镴SP文件移植平臺(tái)時(shí)不能正確顯示的問(wèn)題,對(duì)于這類問(wèn)題,我們了解了JAVA中程序編碼轉(zhuǎn)換的原理,解決起來(lái)就容易多了。我們建議的解決辦法如下:

              1、我們要保證JSP向客戶端輸出時(shí)是采用中文編碼方式輸出的,即無(wú)論如何我們首先在我們的JSP源代編中加入以下一行:

              <%@page contentType="text/html; charset=gb2312"%>

              2、為了讓JSP能正確獲得傳入的參數(shù),我們?cè)贘SP源文件頭加入下面一句:
              <%request.setCharacterEncoding("GB2312");%>

              3、為了讓JSP編譯器能正確地解碼我們的含有中文字符的JSP文件,我們需要在JSP源文件中指定我們的JSP源文件的編碼格式,具體來(lái)說(shuō),我們?cè)贘SP源文件頭上加入下面的一句即可:
              <%@page pageEncoding="GB2312"%>或<%@page pageEncoding="GBK"%>
              這是JSP規(guī)范2.0新增加的指令。

              我們建議使用此方法來(lái)解JSP文件中的中文問(wèn)題,下面的代碼是一個(gè)正確做法的JSP文件的測(cè)試程序:

          //testchinese.jsp
              <%@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>你通過(guò)URL傳入的字符為:"+str);
              }
              %>
              </body>
              </html>
              如圖7是此程序運(yùn)行的結(jié)果示意圖:

              圖7

              5、總結(jié)

              在上面的詳細(xì)分析中,我們清晰地給出了JAVA在處理源程序過(guò)程中的詳細(xì)轉(zhuǎn)換過(guò)程,為我們正確解決JAVA編程中的中文問(wèn)題提供了基礎(chǔ)。同時(shí),我們給出了認(rèn)為是最優(yōu)的解決JAVA中文問(wèn)題的辦法。

              6、參考資料
               1、段明輝.Java 編程技術(shù)中漢字問(wèn)題的分析及解決.
                  http://www-900.ibm.com/developerWorks/cn/java/java_chinese/index.shtml
               2、 周競(jìng)濤.關(guān)于Java中文問(wèn)題的幾條分析原則
                  http://www-900.ibm.com/developerWorks/cn/java/l-javachinese/index.shtml

          posted on 2007-07-04 15:22 王君 閱讀(225) 評(píng)論(1)  編輯  收藏 所屬分類: J2SE

          Feedback

          # re: 深入剖析Java編程中的中文問(wèn)題(二) 2007-07-13 15:57 meggie
          非常感謝你的這篇文章,同時(shí)非常佩服你的總結(jié)分析能力。
          但我還是有幾個(gè)問(wèn)題想問(wèn)問(wèn):
          1、如果我們系統(tǒng)統(tǒng)一使用UTF-8編碼,是不是應(yīng)該把gb2312的地方改為UTF-8, 但好象有問(wèn)題。
          2、如果我們jsp1.0,不支持pageEncoding設(shè)置,應(yīng)該用什么替代
          3、jsp版本比較低,不支持request.setCharacterEncoding(),如何解決輸入中文問(wèn)題
          4、request.setCharacterEncoding() 是否同時(shí)解決URL中的漢字和FORM中的漢字問(wèn)題  回復(fù)  更多評(píng)論
            

          主站蜘蛛池模板: 新乡县| 武邑县| 东至县| 南郑县| 翼城县| 山丹县| 朝阳市| 石渠县| 双城市| 贵德县| 葵青区| 太和县| 湘潭县| 墨玉县| 大石桥市| 来安县| 高碑店市| 巴塘县| 游戏| 安平县| 白河县| 天柱县| 若尔盖县| 宁陵县| 东山县| 广平县| 隆尧县| 山东省| 柳林县| 汝州市| 安义县| 育儿| 夹江县| 建昌县| 万源市| 阿克陶县| 崇义县| 汤阴县| 五莲县| 罗平县| 阜宁县|