JAVA基礎:Java多語言編碼問題解析

來源:互聯網
上載者:User
 1、Java編譯器在對源檔案編譯前,會先把源檔案轉換為unicode編碼,因為這個原因,我們在編譯時間一定要把源檔案用的是什麼編碼方式正確無誤的”告訴”編譯器。

  例如:我們的源檔案是以UTF-8的方式儲存的,而在編譯時間編譯器卻把它當作是用GBK方式儲存的,這樣編譯器就會按照GBK->Unicode的編碼轉換方法對源檔案進行轉換,然後再編譯,這樣當然會出錯,實際上編譯器應當按照UTF-8->Unicode的編碼轉換方法來對源檔案進行轉換。

  a.對於控制台程式,編譯器會把源檔案看作是由系統預設的編碼類別型來編碼的(系統預設的編碼類別型取決於在控制台地區設定裡的配置,中文win2k下通常是GBK),也可以使用-encoding參數來設定,如:javac -encoding UTF-8,這樣編譯器就會把源檔案看作是用UTF-8編碼的(這隻是告訴編譯器源檔案的編碼類別型,而不是對源檔案轉碼)。在各種語言的平台上只要在編譯用時-encoding指定與源檔案的編碼相同的編碼方式,就不會存在國際化的問題了。

  b.對於JSP,編譯器則會根據設定的字元集來判斷JSP檔案使用的是什麼編碼方式,進而將其轉換成unicode後進行編譯;若JSP中未指定,編譯器則會把JSP檔案看作是按照系統預設的編碼來儲存的。在JSP2.0裡新增了一個指令來通知編譯器這個源檔案所使用的編碼方式。

  2、在處理輸入輸出時,注意設定輸入資料流和輸出資料流的編碼類別型與使用者輸入時和輸出裝置顯示時採用的編碼方式一致。

  由於JRE在處理輸入輸出時會將輸入或輸出的內容進行編碼轉換,對於輸入會轉換為unicode後再送入,因此要正確的匹配實際輸入內容的編碼方式和告知JRE的編碼方式,對於輸出,會由unicode轉換為其他的編碼再送出程式,因此要正確匹配輸出裝置顯示時用的編碼方式和告知JRE的編碼方式。

  例如:程式中設定輸入資料流的編碼是new InputStreamReader(System.in,"GB2312");而程式運行後使用者輸入時用了繁體中文的IME,輸入了BIG5編碼的內容,這樣JRE把BIG5編碼的內容當作GB2312的進行了GB2312->unicode的編碼轉換,這樣轉換後的結果顯然不是使用者想要輸入的內容了。

  預設情況下,JRE會把輸入輸出的內容當作是按照系統預設編碼方式編碼的。

  3、在Servlet中,除了一定要把源檔案用的是什麼編碼方式正確無誤的”告訴”編譯器外,還要注意實際提交的URL資料、表單資料的編碼格式和request中聲明的編碼格式一致。

  用戶端瀏覽器在通過表單和URL提交資料時,容器和JVM會將request中的資料看作是按照request所聲明的編碼方式來編碼的,將資料由這種編碼方式轉換為unicode後再送入servlet(實際上容器會先將request中的資料轉為一種中間編碼方式,具體根據容器的配置而定,再由JVM由這種中間方式轉換為unicode,通常這種中間格式是ISO)。servlet輸出的unicode資料會由容器根據response中聲明的編碼方式進行轉換,再送到用戶端瀏覽器上。

  在接收用戶端輸入時,用request.setCharacterEncoding()聲明請求中資料的編碼方式。

  在向用戶端輸出時用response.setContentType("text/html;charset=");聲明響應的資料的編碼方式,告知瀏覽器以哪種編碼方式顯示。

  4、在JSP中,由於JSP本就會被JSP編譯器編譯為servlet來運行,因此情況與servlet相同。

  這兩個JSP指令聲明了請求和響應的編碼方式。

  只要確保URL參數或表單中資料的編碼方式和所聲明的編碼方式一致,再通過告知JSP編譯器本JSP檔案採用的編碼方式及含有哪種字元,即可解決JSP的字元編碼問題。

  這裡是一個具體的例子:

  現在因為瀏覽器對UTF-8的支援,我們可以通過在源檔案、請求、響應中都使用unicode編碼方式,來輕鬆達到處理國際化和字元編碼問題的目標。

  以我們使用的tomcat4.1.2為例,過程如下:

  1、編寫JSP頁面時:在每個JSP頁面在頁首都要增加一行:

  在編輯JSP頁面時,一定要確保JSP檔案以unicode的方式儲存,目前幾乎所有的編輯器都有以unicode編碼儲存或將檔案內容轉換成unicode的功能。

  2、增加一個用來聲明request的CharacterEncoding的類SetCharacterEncodingFilter.java;

  SetCharacterEncodingFilter的這個類主要的作用就是:把request在從頁面剛提交到server端的時候的encoding聲明為我們想要的encoding,通過調用request的方法setCharacterEncoding (String encoding) 來改變,這樣可以使request的從用戶端傳過來的時候,按我們在web.xml (在第二點可以講到) 中配置的encoding來對提交的資料編碼。

  3、修改web.xml檔案,配置一個filter來過濾全部url請求,通過第二步中的類,聲明所有url請求的編碼類別型未UTF-8。

  在web.xml檔案中加上以下這段:

  

 Set Character Encoding
  org.kyle.web.sample.SetCharacterEncodingFilter
                       
     

encoding
     

UTF-8

   Set Character Encoding
   /*

  在上面這段文字中“org.kyle.web.sample.SetCharacterEncodingFilter”指定步驟2中的類的位置,“ UTF-8”指定我們希望聲明的request的編碼類別型,“/*”指定這個filter的適用範圍(這裡指的是全部url請求)。

同時注意二個問題:

  1:servlet的版本必需是支援request.setCharacterEncoding(String encoding)這個方法才行,也就是在serlvert2.3以上。

  2:控制台地區設定的當前字碼頁屬性必需設定為"936 (GBK)",如果是"437(OEM-United States)"它處理文字的時候是8-bit,而中文和日文等是16-bit。所以在顯示和處理時它把中文的前8位給截掉,這樣就會出現亂碼問題。

  附:SetCharacterEncodingFilter源檔案

  

package org.kyle.web.sample;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.UnavailableException;
public class SetCharacterEncodingFilter implements Filter
{
    /**
     * The default character encoding to set for requests that pass through
     * this filter.
     */
    protected String encoding = null;
    /**
     * The filter configuration object we are associated with.  If this value
     * is null, this filter instance is not currently configured.
     */
    protected FilterConfig filterConfig = null;

    /**
     * Should a character encoding specified by the client be ignored?
     */
    protected boolean ignore = true;

    /**
     * Take this filter out of service.
     */
    public void destroy()
    {
        this.encoding = null;
        this.filterConfig = null;
    }

    /**
     * Select and set (if specified) the character encoding to be used to
     * interpret request parameters for this request.
     *
     * @param request The servlet request we are processing
     * @param result The servlet response we are creating
     * @param chain The filter chain we are processing
     *
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet error occurs
     */
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain)
 throws IOException, ServletException
 {

        // Conditionally select and set the character encoding to be used
        if (ignore || (request.getCharacterEncoding() == null))
        {
            String encoding = selectEncoding(request);
            if (encoding != null)
                request.setCharacterEncoding(encoding);
        }

 // Pass control on to the next filter
        chain.doFilter(request, response);
    }

    /**
     * Place this filter into service.
     *
     * @param filterConfig The filter configuration object
     *                   
     *encoding
     * UTF-8
     *
     */
    public void init(FilterConfig filterConfig) throws ServletException
    {
        this.filterConfig = filterConfig;
        this.encoding = filterConfig.getInitParameter("encoding");
        String value = filterConfig.getInitParameter("ignore");
        if (value == null)
            this.ignore = true;
        else if (value.equalsIgnoreCase("true"))
            this.ignore = true;
        else if (value.equalsIgnoreCase("yes"))
            this.ignore = true;
        else
            this.ignore = false;
    }

    /**
     * Select an appropriate character encoding to be used, based on the
     * characteristics of the current request and/or filter initialization
     * parameters.  If no character encoding should be set, return
     * null.
     *

     * The default implementation unconditionally returns the value configured
     * by the encoding initialization parameter for this
     * filter.
     *
     * @param request The servlet request we are processing
     */
    protected String selectEncoding(ServletRequest request)
    {
        return (this.encoding);
    }
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.