截取中文字符的一些注意事項

小弟在對接業務的時候 要求將數據寫入文件,GBK格式,上傳,下載也是GBK的。但出現了一種狀況,獲取文件中一行內容後,截取一段有中文的數據,就會出現    截取結果的長度要大於輸入的長度,好比我截取6個字符長度,但實際卻截取了8個長度。截取方法是String的subString方法。app

仔細查看後才知道,subString的方法是默認將字符都處理成--UCS2字符,因此長度會有變化。測試

通過一番查找最後得出 ,要截取字符串以前都須要對字符進行處理ui

 

如下是代碼編碼

public static void main(String args[]) throws UnsupportedEncodingException {
       String str = "我ABC。漢DEF";
       System.out.println("-----字符串的字節長度是:"+str.getBytes().length+"-----");

       char[] arr = str.toCharArray();
       //測試isNotChinese方法
       char aaa = '。';
       System.out.println("====第一個字符是不是漢字?"+isNotChinese(aaa)+"==,很明顯 不認識中文標點符號===");
       System.out.println("====第二個字符是不是漢字?"+isNotChinese(arr[1])+"=====");
       //漢字個數---測試isChinese方法
       int count = 0;
       for (int i = 0; i < arr.length; i++) {
           char ai = arr[i];
           if(isChinese(ai)){
               count++;
           }
       }
       System.out.println("----判斷有幾個漢字-----");
       System.out.println(count);
       //截取指定開始位置 和長度的字節,可轉換成GBK
       System.out.println(btyeSubstring(str,6,0));



   }

   /**
    * 按照字節對字符串進行截取
    * @param str
    * @param count
    * @param start
    * @return
    * @throws UnsupportedEncodingException
    */
   public static String btyeSubstring(String str,int count,int start) throws UnsupportedEncodingException {
       //串不能爲空
       if(null != str && !"".equals(str)){
           //對參數進行字符轉換
           str = new String(str.getBytes(),"UTF-8");
           //判斷要截取的字節數
           if(count > 0 && count < str.getBytes("UTF-8").length){
               StringBuilder buff = new StringBuilder();
               char c;
               for(int i = start; i < count; i++){
                   //按照須要截取的長度 0-count  進行截取,char類型,按字節截取
                   c = str.charAt(i);
                   buff.append(c);
                   //判斷c 是否是漢字,若是是,則截取的長度要縮減1
                   if(isChinese(c)){
                       --count;
                   }
               }
               return new String(buff.toString().getBytes(),"UTF-8");
           }
       }
       return str;
   }

   /**
    * 判斷是不是中文相關字符
    * @param c
    * @return
    */
   public static 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.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
               || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
               || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) {
           return true;
       }
       return false;
   }

   /**
    * 判斷漢字,不能判斷中文符號
    * @param c
    * @return
    */
   public static boolean isNotChinese(char c){
       //0x4E00   0x9FA5是漢字在unicode 16進制編碼中的區間值
       return (c >= 0x4E00 &&  c <= 0x9FA5) ? true : false;
   }

 

注意:0x4E00 ,0x9FA5是漢字在unicode 16進制編碼中的區間值,判斷漢字足夠,但判斷中文標點就不行了。須要使用Character.UnicodeBlock 指定的屬性進行判斷。code

相關文章
相關標籤/搜索