Mister4  
          突破,從積累開始
          日歷
          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345
          統計
          • 隨筆 - 3
          • 文章 - 4
          • 評論 - 0
          • 引用 - 0

          導航

          常用鏈接

          留言簿

          隨筆檔案

          文章檔案

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

           
          亂碼問題經常碰到,而且每次都要花很久時間才能解決。最近想搞清楚一些實質性的東西,看了一些關于這方面的資料,在這里做個記錄
              造成字符亂碼問題的原因有兩個:
              1是編碼很解碼的方式不一致,
              2是采用了錯誤的編碼造成數據丟失。
              由于計算機的最小存儲單元是字節即8位二進制數,中文是無法在內存中直接表示的,所以從字符到字節就需要通過某個規則轉換即編碼
             編碼方式有很多 我比較常用的是utf-8 GBK iso-8859-1和ASCII,這些都可以看成是字典表。
             比如我用utf-8的方式去編碼字符串"你好"
                  String str = "你好";
                  byte[] utf8 = str.getBytes("utf-8");
                  for(byte b : utf8){
                      System.out.print("  "+b);
                  }
              輸出的結果是:   -28  -67  -96  -27  -91  -67
              說明“你好”這個字符串被編碼成了 6個字節,utf-8是用三個字節表示一個中文字符的,這種轉換過程相當于我們查字典
              如果用GBK編碼
                  String str = "你好";
                  byte[] gbk = str.getBytes("GBK");
                  for(byte b : gbk){
                      System.out.print("  "+b);
                  }
              得到的結果是:  -60  -29  -70  -61   GBK是用兩個字節表示一個中文字符的(需要注意getBytes()這個方法有兩種形式 一個是帶參數一個不帶參數,
              不帶參用系統默認編碼,中文windows操作系統一般都是GBK  一種查看系統編碼的方式是用命令行chcp 936表示GBK)
              到這里我們就可以解釋我們的第一個原因
              比如我們用從網絡中去抓取數據的時候,對方用GBK方式進行編碼,我們拿到字節流的時候用utf-8進行解碼,
              百度用的是GBK編碼
                  URL url = new URL("http://www.baidu.com/");
                  URLConnection connection = url.openConnection();
                  InputStream inputStream = connection.getInputStream();
                  InputStreamReader reader = new InputStreamReader(inputStream, "utf-8");
                  BufferedReader bufferedReader = new BufferedReader(reader);
                  System.out.println("bufferedReader = " + bufferedReader.readLine());
               得到的結果是:
               bufferedReader = <!doctype html><html><head><meta http-equiv="Content-Type" content="text/html;charset=gb2312"><title>?????????????  。。。。
               如果是GBK解碼字節流得到如下的結果
               <!doctype html><html><head><meta http-equiv="Content-Type" content="text/html;charset=gb2312"><title>百度一下,你就知道 。。。。
               由于編解碼方式不一致,utf8去解碼字節流的時候從“字典”中查不到相應的字符,
               默認(有幾種  “?"也是我們經常見到的一種)用U+003F代替 即 “?”
               這里有個問題我還沒有搞清楚,我用GBK編碼”你好“再用utf-8解碼得到的是3個”?“  為什么是3個"?"
               如果了解utf-8 GBK和iso-8859-1等這些的具體編碼方式,第二個問題就比較清楚了。
               比如iso-8859-1是單字節編碼的,比起ASSCII,iso-8859-1把一個字節的最高位也納入進來表示字符,但是最多也只有256個字符,
               實際上它是在ASSCII基礎之上加入了一些西歐字符,并沒有加入中文,所以iso-8859-1也不能表示中文,如果我們這么寫
               String str = "你好";
               byte[] bytes = str.getBytes("iso-8859-1");
               System.out.println("bytes = " + new String(bytes,"utf-8"));        /////輸出 ??
               System.out.println("bytes = " + new String(bytes,"GBK"));              /////輸出 ??
               System.out.println("bytes = " + new String(bytes,"iso-8859-1"));     /////輸出 ??
               由于在“字典”中找不到相應的值,就用3f替代 我們用上面的方式打印 得到的都會是"??",
              java用的是Unicode編碼,API中Character類下有描述:“字符信息基于 Unicode 標準,版本 4.0。。。”
              更實際的Web編程中遇到的瀏覽器顯示亂碼和應用程序接收提交過去的亂碼問題以下博客中都有詳細的描述,
              解決問題總得規則是編碼方式和解碼方式最好保持一致,然后再找出傳輸過程中那些地方是有編解碼的。

              參考鏈接:深入分析 Java 中的中文編碼問題
                            字符編碼筆記:ASCII,Unicode和UTF-8
          posted on 2012-01-04 17:28 Mister4 閱讀(254) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
           
          Copyright © Mister4 Powered by: 博客園 模板提供:滬江博客
          主站蜘蛛池模板: 双桥区| 永仁县| 勃利县| 南郑县| 商水县| 稷山县| 永胜县| 丹巴县| 清原| 拜泉县| 尤溪县| 合山市| 蒙山县| 工布江达县| 如皋市| 象山县| 凌海市| 沙河市| 洛南县| 施秉县| 鄂州市| 淮安市| 保德县| 定日县| 永修县| 土默特右旗| 马公市| 茶陵县| 榆社县| 福泉市| 阿尔山市| 定安县| 东丽区| 登封市| 喀什市| 张家港市| 三台县| 峨边| 无极县| 阳曲县| 霸州市|