ゞ沉默是金ゞ

          魚離不開水,但是沒有說不離開哪滴水.
          posts - 98,comments - 104,trackbacks - 0
                   今天把JAVA里一個比較頭痛的問題“字符編碼”研究了一下,分享一下。

            眾所周知,JAVA為了國際通用,用的是UNICODE來保存里面的字符。而UNICODE只是一個種字符集,字符的存儲和表示要用到一定的字符編碼格式,而與UNICODE對應的字符編碼格式就是我們常看到的UTF-8,UTF-16等等,而UTF-8是最常用的,所以人們常常把它和UNICODE等同起來,這在某些情況下是沒有錯的,但這樣的理解在JAVA里就會產生一些混淆。我們用下面的程序來演示一下。

            定義一個字符串

            String name = "堂";

            這個字符串就一個字符,把它取出來

            char c_name = name.charAt(0);

            JAVA里的char型是十六位的(兩個字節),但是如果是用UTF-8的話可能會不只兩位(UTF-8是變長存儲的),那看來JAVA本身并不是用UTF-8來保存的,口說無憑,做個實驗吧。

            首先看看char里保存的內容  
          int low = (c_name) & 0xff;//取c_name的低位
          int high = (c_name >> 8) & 0xff;//取c_name的高位
          System.out.println(Integer.toHexString(high) + " " + Integer.toHexString(low));
            結果是58 02

            只有兩個字節而已(16位),那么真正的UTF-8編碼的內容是什么呢,再看看吧。

            為了方便,我寫了一個輔助方法printbyte,作用是把一個byte數組的每個元素按照十六進制格式打印出來,同樣為了方便,我把它作為靜態方法。 

           public static void printbyte(byte[] bt)
           {
                for (int i = 0; i < bt.length; i++)
                {
                        int hex = (int)bt[i] & 0xff;
                        System.out.print(Integer.toHexString(hex) + " ");
                }
                System.out.println(" length = "+bt.length);
           }


           byte[] utf_8 = name.getBytes("utf-8");
           printbyte(utf_8);

            結果是e5 a0 82 length = 3

            哇,三個字節!看來JAVA內部用的真不是UTF-8,那用的是什么呢?UTF-16?看一下便知。  
          byte[] utf_16 = name.getBytes("utf-16");
          printbyte(utf_16);
            結果是fe ff 58 02 length = 4,靠,四個字節了。咦?后面的低16位不正是和開始c_name的十六進制表示一樣的嗎?看來JAVA真正的內部字符編碼和UTF-16有或多或少的聯系。JAVA內部究竟是用的什么字符編碼呢?這個問題我也找了很久,后來在THINK IN JAVA 3rd的12章里看到一個例子出現了UTF-16BE,難道是它?  
          byte[] utf_16be = name.getBytes("utf-16be");
          printbyte(utf_16be);
          結果出來了:58 02 length = 2
            哈哈,I got it!不多不少兩個字節,內容也一樣。果然是它。同時我在里面也看到,UNICODE的編碼還有一個LE,這里的BE,LE我想應該是bigendian和littleendian吧。

              附上全代碼:
              

          public class CodeTest {
              
          public static void printbyte(byte[] bt) {
                  
          for (int i = 0; i < bt.length; i++{
                      
          int hex = (int) bt[i] & 0xff;
                      System.out.print(Integer.toHexString(hex) 
          + " ");
                  }

                  System.out.println(
          " length = " + bt.length);
              }


              
          public static void main(String[] args) throws Exception {
                  String name 
          = "";
                  
          char c_name = name.charAt(0);
                  
                  System.out.println(c_name);
          // JAVA里的char型是十六位的(兩個字節)
                  
                  
          int low = (c_name) & 0xff;// 取c_name的低位
                  int high = (c_name >> 8& 0xff;// 取c_name的高位
                  System.out.println(Integer.toHexString(high) + " "
                          
          + Integer.toHexString(low));  //58 2
                  
                  
          byte[] utf_8 = name.getBytes("utf-8");
                  printbyte(utf_8);  
          //e5 a0 82  length = 3
                  
                  
          byte[] utf_16 = name.getBytes("utf-16"); 
                  printbyte(utf_16);  
          //fe ff 58 2  length = 4
                  
                  
          byte[] utf_16be = name.getBytes("utf-16be"); 
                  printbyte(utf_16be); 
          //58 2  length = 2
                  
                  
          byte[] utf_16le = name.getBytes("utf-16le");
                  printbyte(utf_16le); 
          // 2 58  length = 2
              }

          }
          posted on 2008-12-30 14:53 ゞ沉默是金ゞ 閱讀(223) 評論(0)  編輯  收藏 所屬分類: Java SE
          主站蜘蛛池模板: 满洲里市| 丹巴县| 晋中市| 揭西县| 河南省| 泽库县| 土默特右旗| 吉林市| 阿瓦提县| 利辛县| 丹阳市| 通河县| 赫章县| 东乡县| 边坝县| 乌拉特前旗| 衡水市| 齐河县| 镶黄旗| 铜川市| 巴林左旗| 上思县| 攀枝花市| 唐山市| 麻城市| 朝阳区| 唐海县| 富裕县| 扎赉特旗| 沭阳县| 克东县| 和林格尔县| 亚东县| 南溪县| 攀枝花市| 灵川县| 西丰县| 壤塘县| 临湘市| 临猗县| 陕西省|