2015-10-24 33 views
1

我有一個包含表情符號,符號下面的XML文件:http://pastebin.com/8f0GeE96轉換的unicode符號,它們的代碼

現在,我要的是它的代碼,每個Unicode字符轉換(字符串)。我爲此寫了下面的代碼。問題是我得到了很多dup(即d83d),這讓我覺得我的解析有些問題。這是什麼解釋?

public static void main(String[] args) { 

     File file = new File("c:\\EmojisList.plist.txt"); 

     try { 
      BufferedReader in = new BufferedReader(
         new InputStreamReader(new FileInputStream(file), "UTF8")); 

      String str; 
      while ((str = in.readLine()) != null) { 
       if(str.trim().startsWith("<string>")) 
       { 
        int emoji_pos = str.indexOf('>') + 1; 
        char emoji_char = str.charAt(emoji_pos); 
        String emoji_code_str = Integer.toHexString(emoji_char); 

        System.out.println(emoji_code_str); 
       } 

      } 

      in.close(); 


     } catch (UnsupportedEncodingException e) { 
      e.printStackTrace(); 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

回答

1

Unicode標準從16位(兩個字節)就足夠的字符範圍開始。

但是,越來越多的腳本和符號被添加到它,現在,你不能用16位表示所有的字符。碼點的合法範圍是從U + 0到U + 10FFFF。

不幸的是,這不符合Java char,它只有16位,並且能夠表示值0到FFFF。

最常見的西方語言對此沒有任何問題 - 拉丁語的範圍包括口音,俄語,阿拉伯語,希伯來語等等,都在16位範圍內。即使是普通的中文和日文字符也在這個範圍內。

但是大多數表情符號實際上都在「擴展」範圍內,在U + 1F300到U + 1F5FF和U + 1F600到U + 1F67F範圍的unicode「Miscellaneous Symbols and Pictographs」和「Emoticon」分別。

此範圍內的字符使用UTF-16編碼以字符串表示,對於每個此類字符,基本上都使用兩個char值。所以如果一個字符的代碼點(它的官方unicode值)在U + 10000到U + 10FFFF的範圍內,則有兩個char的值,一個來自U + D800到U + DB7F的範圍(「高代理」)和一個從U + DC00到U + DFFF(「低代用品」)的範圍用於表示它。

因此,當您在程序中讀取charAt(emoji_pos)的值時,實際上只讀取了實際字符的前半部分。事實上,「表情符號」範圍內的所有表情符號都具有U + D83D的高代表性。

因此,要獲取表情符號的實際Unicode代碼點,您需要將UTF-16表示法轉換爲實際的int值。 A char是不夠的。您可以使用StringCharacter類中的可用方法執行此操作。

而不是使用charAt,在這種情況下,您可以簡單地使用codePointAt方法。

所以,與其

char emoji_char = str.charAt(emoji_pos); 

用途:

int emojiCodePoint = str.codePoint(emojiPos); 

欲瞭解更多信息,請在Unicode協會的網站上閱讀UTF FAQ


注:Java編碼慣例是可變的,現場的方法名稱應該是較低的駱駝情況:第一個字用小寫字母開頭,其他詞開始以大寫字母,以及沒有強調 。所以變量名應該是emojiCodePoint,而不是emoji_code_point。下劃線僅適用於全名大寫的常數名稱(例如CASE_INSENSITIVE_ORDER)。

+0

非常感謝你的詳細解答! – hibye

相關問題