2011-03-07 66 views
1

我想將CJK ExtB計劃中包含Unicode字符的Java字符串轉換爲十進制NCR。在Java/Scala中將Unicode(CJK ExtB)字符轉換爲十進制NCR

例如(您可以用http://people.w3.org/rishida/tools/conversion/嘗試):

  • 「遊鍚堃」 應該轉換爲游鍚堃
  • 「懷」 應該轉換爲𧦧懷

這裏是我試過(在斯卡拉):

def charToHex(char: Char) = "&#%d;" format(char.toInt) 
def stringToHex (string: String) = string.flatMap(charToHex) 

println (stringToHex("遊鍚堃")) // 游鍚堃 
println (stringToHex("懷")) // ��懷 
println ("懷".toCharArray().length) // Why it is 3? 

正如你可以se e,它在第一種情況下正確轉換,三個unicode字符轉換爲三個NCR。

但在第二種情況「懷」中,只有兩個unicode字符,但Java/Scala似乎認爲它是一個包含三個字符的字符串。

那麼,這裏發生了什麼,我怎麼能正確地轉換第二種情況就像我提到的網站上的轉換器?非常感謝。

更新:

  • 我的源代碼文件是使用UTF-8。
  • 這裏是 「懷」 .toCharArray()的結果
    • char[] = ?, char.toInt = 55390
    • char[] = ?, char.toInt = 56743
    • char[] = 懷, char.toInt = 25079

現在我想我知道發生了什麼。字符「」在UTF-16中編碼爲0xD85E 0xDDA7,即4字節而不是2字節。所以在轉換爲char數組時,需要2個元素,其中數據類型char只能表示2個字節。

回答

7

Java(以及Scala)對其字符串使用UTF-16編碼,這意味着所有2^16-1以上的unicode代碼點必須用兩個字符表示。 (實際上,編碼方案是bit more complex than that。)無論如何,length是一種在較低級別操作的方法 - 字符 - 因此它返回字符數。

如果你想知道代碼點的數量,當你說「兩個unicode字符」時(例如打印出來的兩個符號),你可能會直覺地想到這些代碼點的數量,你需要使用s.codePointCount(0,s.length)。如果你想將這些轉換爲十六進制,你需要使用不是Char的代碼點,因爲並不是所有的代碼點都適合。我對this question的回答包含Scala代碼,用於將字符串轉換爲代碼點。 (不是最大的效率;如果你正在對大字符串進行重型文本處理,你會想重寫它以使用數組/ ArrayBuffer。)

+0

謝謝,這正是我需要的! – 2011-03-07 10:54:42

0

檢查文件編碼。您的IDE或構建腳本必須知道該文件是UTF-8或UTF-16(您使用哪一個?)。如果你定義了BOM然後檢查它是否合適。

2

這就是他們在unicode中所說的「代理」。例如,

"懷" foreach { c => 
    println(java.lang.Character.UnicodeBlock.of(c)) 
} 

打印

HIGH_SURROGATES 
LOW_SURROGATES 
CJK_UNIFIED_IDEOGRAPHS 

順便說一句,我是總部設在臺灣也是如此。如果你對斯卡拉感興趣,我們應該聚在一起談談商店。如果您有興趣,我的電子郵件在我的個人資料中。

相關問題