熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

分析 Java 中亂碼問題產生的根源

2013-11-23 19:19:20  來源: Java核心技術 

  最近用到了字符串的壓縮用到了GZipInputStream和GZipOutputStream再次遇到了闊別已久的中文亂碼問題
  
  看了一些相關的文章覺得我們之所以會遇到這樣那樣的亂碼問題基本上都是由於我們在某些地方隱含了byte到char的轉換而這種隱含的轉換采用的是iso的編碼進行的
  
  以jsp頁面中文傳遞為例子假設客戶端的編碼是GB表單中的中文提交後首先根據GB編碼轉換為字節流到達服務器端後如果我們直接在servlet中調用requestgetParameter(String name)等方法由於方法返回的是String 對象所以其中必然隱含了一次從byte到char的轉換錯誤也就是在這裡產生的如果這次轉換采用的編碼是iso得到的當然是亂碼
  
  public class Login
  extends HttpServlet {
  private static final String CONTENT_TYPE = text/html; charset=UTF;
  
  //Initialize global variables
  public void init() throws ServletException {
  }
  
  //Process the HTTP Get request
  public void doGet(HttpServletRequest request HttpServletResponse response) throws
  ServletException IOException {
  String name = requestgetParameter(userid);//隱含的轉換
  
  name = new String(namegetBytes(iso) GB);//還原字節重新構造
  
  responsesetContentType(CONTENT_TYPE);
  PrintWriter out = responsegetWriter();
  outprintln(<html>);
  outprintln(<head><title>Login</title></head>);
  outprintln(<body bgcolor=\#ffffff\>);
  outprintln(<p>The servlet has received a GET This is the reply</p>);
  outprintln(</body>);
  outprintln(</html>);
  outclose();
  }
  }
  
  幸好以iso進行的默認轉換不會損失字節也不會增加字節我們只要按照iso的方式返回原來的字節數組重新按照GB的方式進行byte 到char的轉換就可以了
  
  再以壓縮流為例(文件流實際上也是一樣的)
  
  public String uncompress(byte[] cmp) {
  String ret = ;
  int i;
  byte[] buf = new byte[];
  try {
  /**
  *新的方式始終保持以字節為核心最後再按照合適的編碼進行組裝
  */
  BufferedInputStream bis = new BufferedInputStream(new GZIPInputStream(new
  ByteArrayInputStream(cmp)));
  
  /**
  * 以前的方式
  * 在 new InputStreamReader()的時候發生了隱含的byte到char的轉換導致之後出來的都是亂碼
  */
  //   BufferedReader bis = new BufferedReader(new InputStreamReader(new
  //     GZIPInputStream(new
  //             ByteArrayInputStream(cmp))));
  
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  BufferedOutputStream bos = new BufferedOutputStream(baos);
  
  while ( (i = bisread(buf)) > ) {
  boswrite(buf i);
  }
  bosclose();
  baosclose();
  bisclose();
  ret = new String(baostoByteArray());//用平台默認的編碼進行組裝我是GB
  }
  catch (IOException ex) {
  exprintStackTrace();
  }
  
  return ret;
  }
  
  reader是以字符為核心inputStream是以byte為核心的當他們轉換的時候就會進行byte到char的轉換所以我們要注意自己的調用的順序
  
  我們如果今後再遇到亂碼的問題就去找找自己是不是什麼地方進行了隱含的byte到char的轉換
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26652.html
  • 上一篇文章:

  • 下一篇文章:
  • Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.