java中的字節、字符、編碼以及中文亂碼問題

1、中英文編碼

1. 英文字母:A
2. 字節數:1;編碼:GB2312
3. 字節數:1;編碼:GBK
4. 字節數:1;編碼:GB18030
5. 字節數:1;編碼:ISO-8859-1
6. 字節數:1;編碼:UTF-8
7. 字節數:4;編碼:UTF-16
8. 字節數:2;編碼:UTF-16BE
9. 字節數:2;編碼:UTF-16LE
10. 中文漢字:人
11. 字節數:2;編碼:GB2312
12. 字節數:2;編碼:GBK
13. 字節數:2;編碼:GB18030
14. 字節數:1;編碼:ISO-8859-1
15. 字節數:3;編碼:UTF-8
16. 字節數:4;編碼:UTF-16
17. 字節數:2;編碼:UTF-16BE
18. 字節數:2;編碼:UTF-16LE

輸入途徑:
 1、通過頁面表單打包成請求 (request)發往服務器的;
 2、通過數據庫讀入;
 3、JSP在第一次運行時總是被編譯成Servlet,JSP中常常包含中文字符,那麼編譯使用javac時,Java將根據默認的操作系統編碼作爲初始編碼。除非特別指定,如在                    eclipse中可以指定默 認的字符集。
輸出途徑:
 1、JSP頁面的輸出。
 由於JSP頁面已經被編譯成Servlet,那麼在輸出時,也將根據操作系統的默認編碼來選擇輸出編碼,除非指定輸出編碼方式;
 2、數據庫,將字符串輸出到數據庫。
解決中文亂碼的根本辦法是明確指定整個應用系統統一字符集。
  1、指定統一字符集ISO8859_1 、GBK(只能在相應的操作系統上運行):
a. 開發和編譯代碼時指定字符集爲ISO8859_1(GBK)。
b. 運行操作系統的默認編碼必須是ISO8859_1(中文Windows默認是GBK),如Linux。
c. 在JSP頭部聲明:。
  2、UTF-8
 a. 開發和編譯代碼時指定字符集爲UTF-8。Eclipse都可以在項目屬性中設置。
 b. 使用過濾器,如果所有請求都經過一個Servlet控制分配器,那麼使用Servlet的filter執行語句,將所有來自瀏覽器的請求(request)轉換爲UTF-8,因爲瀏覽器                                 發過來的請求包根據瀏覽器所在的操作系統編碼,可能是各種形式編碼。
 關鍵一句request.setCharacterEncoding("UTF-8")。網上有此filter的源碼,Jdon框架源碼中com.jdon.util.SetCharacterEncodingFilter需要配置web.xml 激                                    活該Filter。
 c. 在JSP頭部聲明:在Jsp的html代碼中,聲明UTF-8:
 d. 設定數據庫連接方式是UTF-8。例如連接MYSQL時配置URL如下:jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8, 一般數據                                  庫都可以通過管理設置設定UTF-8
 e. 其他和外界交互時能夠設定編碼時就設定UTF-8,例如讀取文件,操作XML等


Java中文問題的由來:
    Java的內核和class文件是基於unicode的。
     1、Java和JSP文件本身編譯時產生的亂碼問題
 Java(包括JSP)源文件中很可能包含有中文,而Java和JSP源文件的保存方式是基於字節流的,如果Java和JSP編譯成class文件過程中,使用的編碼方式與源文件的編碼不一致,就會出現亂碼。這種情況下建議在Java文件中儘量不要寫中文(註釋部分不參與編譯,寫中文沒關係),如果必須寫的話,儘量手動帶參數-ecoding GBK或-ecoding gb2312編譯;對於JSP,在文件頭加上<%@ page contentType="text/html;charset=GBK"%>或<%@ page contentType="text/html;charset=gb2312"%>基本上就能解決這類亂碼問題
2、Java程序與其他媒介交互產生的亂碼問題
      1) 從頁面form提交數據到java程序 byte->char;從java程序到頁面顯示 char->byte
     頁面參數的編碼類型和系統默認的編碼類型不一致
 request.setCharacterEncoding("gb2312")。如果在JSP將變量輸出到頁面時出現了亂碼,可以通過設置
                  response.setContentType("text/html;charset=GBK")或response.setContentType("text/html;charset=gb2312")解決。
 或者:
  web.xml:
<filter>
 <filter-name>CharacterEncodingFilter</filter-name>
 <filter-class>net.vschool.web.CharacterEncodingFilter</filter-class>
 <init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
 </init-param>
</filter>
<filter-mapping>
 <filter-name>CharacterEncodingFilter</filter-name>
 <url-pattern>/*</url-pattern>
</filter-mapping>


 CharacterEncodingFilter.java:
public class CharacterEncodingFilter implements Filter {
 protected String encoding = null;
 public void init(FilterConfig filterConfig) throws ServletException 
 {
this.encoding = filterConfig.getInitParameter("encoding");
 }
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 
 {
request.setCharacterEncoding(encoding);
response.setContentType("text/html;charset="+encoding);
chain.doFilter(request, response);
 }
               }


  2)從數據庫到java程序 byte->char;從java程序到數據庫 char->byte
                   大部分數據庫都支持以unicode編碼方式,所以解決Java與數據庫之間的亂碼問題比較明智的方式是直接使用unicode編碼與數據庫交互。很多數據庫驅動自動支持unicode,如Microsoft的SQLServer驅動。其他大部分數據庫驅動,可以在驅動的url參數中指定,如如mm的
                   mysql驅動:jdbc:mysql://localhost/WEBCLDB?useUnicode=true&characterEncoding=GBK。   
  3)從文件到java程序 byte->char;從java程序到文件 char->byte
  4)從流到java程序 byte->char;從java程序到流 char->byte
Java讀寫文件最常用的類是FileInputStream/FileOutputStream和FileReader/FileWriter。
其中FileInputStream和FileOutputStream是基於字節流的,常用於讀寫二進制文件。
讀寫字符文件建議使用基於字符的FileReader和FileWriter,省去了字節與字符之間的轉換。
但這兩個類的構造函數默認使用系統的編碼方式,如果文件內容與系統編碼方式不一致,可能會出現亂碼。
在這種情況下,建議使用FileReader和FileWriter的父類:
InputStreamReader/OutputStreamWriter,它們也是基於字符的,但在構造函數中可以指定編碼類型:
InputStreamReader(InputStream in, Charset cs) 和OutputStreamWriter(OutputStream out, Charset cs)。
  
     字符集與字符編碼:
   Unicode編碼系統爲表達任意語言的任意字符而設計。它使用4字節的數字來表達每個字母、符號,或者表意文字(ideograph)。每個數字代表唯一的至少在某種語言中使用的符號。(並不是所有的數字都用上了,但是總數已經超過了65535,所以2個字節的數字是不夠用的。)被幾種語言共用的字符通常使用相同的數字來編碼,除非存在一個在理的語源學(etymological)理由使不這樣做。不考慮這種情況的話,每個字符對應一個數字,每個數字對應一個字符。即不存在二義性。不再需要記錄"模式"了。U+0041總是代表'A',即使這種語言沒有'A'這個字符。
Unicode是字符集,UTF-32/ UTF-16/ UTF-8是三種字符編碼方案




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章