1. gzyueqian
      13352868059

      學習java去哪里好?為什么學習java還需要報java培訓班

      更新時間: 2018-09-29 16:22:30來源: Java培訓瀏覽量:4723

          一道經典問題
          Java里的char類型能不能存儲一個中文字符?
          對于這道題,絕大多數的答案都是“可以存儲”。給出的原因包括:
          1. java中的char是unicode存儲,unicode編碼字符集中包含了漢字,所以可以存儲中文;
          2. java內部其實是使用的UTF-16的編碼,所以是支持大部分非生僻漢字的;
          3. 采用Unicode編碼集,一個char占用兩個字節,而一個中文字符也是兩個字節,因此Java中的char是可以表示一個中文字符的;
          4. Java的char只能表示utf-16中的BMP部分中文字符,不能表示擴展字符集里的中文字符;
          那么,這個問題的答案到底是什么?
          Java API中關于char的說明

          char類型是按照Unicode規范實現的一種數據類型,固定16bit大小。現如今,
          Unicode字符集已經進行了擴展,表示的范圍已經超過了16bit。Unicode字符集的
          數值范圍擴大到了[U+0000,U+10FFFF]。

          也就是說一個char能夠存儲16bit大小的數值,即2個字節。但是,就常用的UTF-8編碼來說,我們都聽說過他是用3或者4個字節來表示一個漢字的。就拿3個字節來算的話,一個char也存不下是不是?
          我們繼續看api文檔的其他段落:

          一個char值可以表示BMP范圍內的Unicode字符。BMP表示[U+0000, U+FFFF]之間的Unicode字符。

          而且,絕大部分的中文字符的Unicode范圍是[0x4E00, 0x9FBB],恰好是在BMP范圍內。
          是不是說這里出現了破解不了的矛盾呢?UTF-8占用3到4個字節,char只能存2個字節(16bit),然而UTF-8中的幾乎所有漢字都是在BMP范圍內,也就是在char可存儲的范圍內,是不是矛盾了?
          答案是不矛盾!關鍵點就在于接下來給出總結的條!
          這里先給出總結,后續再給出解釋:
          1.char字符存儲的是Unicode編碼的代碼點,也就是存儲的是U+FF00這樣的數值,然而我們在調試或者輸出到輸出流的時候,是JVM或者開發工具按照代碼點對應的編碼字符輸出的。
          2. 所以雖然UTF-8編碼的中文字符是占用3個或者4個字節,但是對應的代碼點仍然集中在[0x4E00, 0x9FBB],所以char是能夠存下在這個范圍內的中文字符的。
          3. 但是對于超過16bit的Unicode字符集,也就是Unicode的擴展字符集,一個char是放不下的,需要兩個char才能放下。
          Unicode編碼
          Unicode的出現是對混亂的ANSI編碼世界的一個大一統,因而也叫做統一碼、萬國碼、單一碼。Unicode編碼把世界上常用的語言字符都進行了統一的編碼,一個數值就代表一個字符,而且世界范圍內公認。
          ANSI的編碼世界里,各中語言有自己的編碼規范,同一個數值在不同的國家代表不同的字符。所以當文字在不同國家傳遞的時候(比如發郵件,看國外網頁),問題就很大了,我明明寫的是“愛我中華”,美國朋友看到的確實”°??ò?D?a”,一定是一臉問號!

          //=====模擬文字在不同編碼語言間傳遞的過程=====
          //發帖子
          String s = "愛我中華";
          //編碼成字節流,通過網絡傳入,或者存儲到文件
          byte[] bytes = s.getBytes("GB2312");
          System.out.println(s);
          //國外朋友用自己電腦的編碼方式解析字節流
          String s2 = new String(bytes, "ISO-8859-1");
          //oh! shit, wtf!        
          System.out.println(s2);

          有了Unicode這個統一編碼之后,全世界的計算機都能正確的解析到原始的字符,對于國內的文字信息,國外的朋友要做的就是懂中文!
          UTF-8只是Unicode編碼的一種編碼轉換規范,也就是怎么存儲Unicode代碼點的方案之一。另外還有UTF-16和UTF-32等編碼規范。Unicode為什么需要這么多編碼規范?直接存儲代碼點行不行?
          當然不行,存儲了就需要解析比如”漢字”兩個字的Unicode代碼點是“0x6c49和0x5b57”也就是”6c495b57”。而且,Unicode的代碼點還有3個字節的,比如”10FF3B”,對于一個很長的上述數字串該怎么解析?比如“10FF3B6c495b57”!
          所以,需要某種編碼方案來區分那幾個數值是一個Unicode代碼點,這種方案就是UTF-8、UTF-16、UTF-32這樣的編碼方案。
          UTF-8編碼和代碼點對應關系
          UTF-8以字節為單位對Unicode進行編碼。從Unicode到UTF-8的編碼方式如下:
          Unicode編碼(十六進制) UTF-8 字節流(二進制)
          000000-00007F 0xxxxxxx
          000080-0007FF 110xxxxx 10xxxxxx
          000800-00FFFF 1110xxxx 10xxxxxx 10xxxxxx
          010000-10FFFF 11110xxx10xxxxxx10xxxxxx10xxxxxx
          有沒有發現點什么?當一個字節表示一個字符時,二進制開頭是0;當兩個字節表示一個字符時,二進制開頭是11;當3個字節表示一個字符時,二進制開頭是111;依次類推!
          UTF-8編碼加入了多余的標識位來區分一個Unicode代碼點!才會出現中文漢字集中在[0x4E00, 0x9FBB]范圍的16bit數值內,UTF-8卻需要3個字節存儲的原因。
          另一個經典問題
          怎么判斷Java字符串是否包含中文?
          這個問題也很經典,一般我們可以查到的方法如下:

          //代碼來自HanLP自然語言處理庫,git地址:https://github.com/hankcs/HanLP/blob/master/src/main/java/com/hankcs/hanlp/utility/TextUtility.java
          /**
           * 判斷某個字符是否為漢字
           *
           * @param c 需要判斷的字符
           * @return 是漢字返回true,否則返回false
           */
          public static boolean isChinese(char c)
          {
              String regex = "[\u4e00-\u9fa5]";
              return String.valueOf(c).matches(regex);
          }

          // GENERAL_PUNCTUATION 判斷中文的“號  
              // CJK_SYMBOLS_AND_PUNCTUATION 判斷中文的。號  
              // HALFWIDTH_AND_FULLWIDTH_FORMS 判斷中文的,號  
              private static final boolean isChinese(char c) {  
                  Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);  
                  if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS  
                          || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS  
                          || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A  
                          || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION  
                          || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION  
                          || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {  
                      return true;  
                  }  
                  return false;  
              }

          總結一下,一般來說用種方法就足夠了,擴展字符集用的比較少,另外從HanLP的github星數來說,這種方案的通用度還是可信的。
          好了,先到這里。這里也留一個坑,mysql數據庫里邊的VARCHAR類型和Java的char類型是一種處理方式么?

      免費預約試聽課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 五月天丁香婷婷激情综合 | 三级在线免费a免费看 | 真实国产乱子伦视频 | 婷婷在线免费公开视频 | 亚洲日韩精品欧美国产动漫第一页 | 一区二区三区中文字幕在线 |