2010-03-28 136 views
31

Java char2 bytes(最大大小爲65,536),但有95,221 Unicode字符。這是否意味着您無法在Java應用程序中處理某些Unicode字符?Java Unicode編碼

這是否歸結爲您正在使用什麼字符編碼?

回答

32

如果您足夠小心,可以處理它們。

Java的charUTF-16 code unit。對於代碼點> 0xFFFF的字符,它將用2 char s(代理對)進行編碼。

有關如何處理Java中的這些字符,請參見http://www.oracle.com/us/technologies/java/supplementary-142654.html

(順便說一句,以Unicode 5.2有107154個分配字符出來1,114,112槽。)

+1

上面所鏈接的頁面是我在不同的編碼,什麼JVM API使用區分閱讀最明顯的一個,某些用語的含義(「碼點」與「代碼單元」)以及JNI提供了什麼。 – 2011-12-08 02:57:47

+0

以下網站非常明確,但相當詳細。它甚至超越了碼點的定義,並說明如何處理和計算字形(完成渲染的字符使用組合子變音符號時,它可以由一個以上的碼點的)http://illegalargumentexception.blogspot.jp/2009/ 05/Java的粗糙引導至字符-encoding.html – 2012-08-05 09:25:16

+1

@ AllenGeorge的審查後,我很興奮地閱讀文章,才發現該鏈接現在是打破:(紅潤Oracle和他們的無能301正常工作。任何人都可以更新鏈接? – dimo414 2013-02-08 16:13:34

1

OpenJDK7 documentation for String

的String表示在 UTF-16格式的字符串,其中補充 字符由 替代對(參見 中的Unicode字符表示 字符類更多 信息)表示。索引值是指 字符代碼單元,因此補充 字符使用 字符串中的兩個位置。

14

Java使用UTF-16。一個Java char只能表示來自basic multilingual plane的字符。其他字符必須由兩個char s的替代對來表示。這反映在API方法中,例如String.codePointAt()

是的,這意味着很多Java代碼在與基本多語言平面之外的字符一起使用時會以某種方式破壞。

+2

怎麼辦'String.length','substring'等處理字符串 – 2011-08-28 14:19:49

+5

@Bart:長度()計算這樣的字符作爲兩個字符,子()也會很高興地打破它們,重新分類ng以無效的UTF-16格式。這是因爲這些字符只有在設計Java之後才成爲Unicode的一部分,並且Java不會發生重大更改。因此,增加了新的方法來處理代理對,但舊方法保持不變。 – 2011-08-28 15:37:20

+2

+1,指出大多數Java代碼已損壞。 – ceving 2013-06-28 09:27:49

3

看看Unicode 4.0 support in J2SE 1.5文章,瞭解更多關於Sun發明的技巧,以提供對所有Unicode 4.0代碼點的支持。

總之,您將在Java 1.5中找到對Unicode 4.0以下變化:

  • char是UTF-16代碼單元,而不是一個代碼點
  • 新的低級別的API使用int表示Unicode代碼點
  • 高級API已更新以瞭解代理對
  • 對char序列API的偏好而不是基於char的方法

由於Java沒有32個字符,我就讓你判斷,如果我們可以把這種良好的Unicode支持。

10

要添加到其他的答案,要記住的幾點:

  • 一個的Java char需要始終16位

  • A Unicode字符,當編碼爲UTF-16時,幾乎總是(不總是)16位:這是因爲有超過64K的Unicode字符。因此,Java字符不是Unicode字符(儘管「幾乎總是」)。

  • 上面的「幾乎總是」表示Unicode的64K個第一代碼點,範圍爲0x0000到0xFFFF(BMP),它們在UTF-16編碼中佔用16位。

  • 非BMP(「罕見」)Unicode字符表示爲兩個Java字符(代理表示)。這也適用於字符串的字面表示:For example, the character U+20000 is written as "\uD840\uDC00".

  • Corolary:string.length()返回java字符的數量,而不是Unicode字符的數量。只有一個「罕見」Unicode字符的字符串(例如U + 20000)將返回length() = 2。同樣的考慮適用於處理字符序列的任何方法。

  • Java對於處理非BMP的unicode字符整體而言沒有什麼智能。有一些實用方法將字符視爲代碼點,用int表示,例如:Character.isLetter(int ch)。這些是真正的完全Unicode方法。

+0

難道你不是指0x0000到0xFFFF?你只寫3 F的。 – JoelFan 2017-09-20 21:34:47

+0

@JoelFan修正,謝謝。 – leonbloy 2017-09-21 03:38:02

2

以下是有關Unicode Character Representations的Oracle文檔。或者,如果你願意,more thorough documentation here

char數據類型(因此,一個字符對象 封裝值)基於原始Unicode規範,其定義 字符作爲固定寬度的16位實體。 Unicode 標準此後被更改爲允許表示要求多於16位的字符。合法代碼 點的範圍現在是U + 0000到U + 10FFFF,稱爲Unicode標量值。 (請參閱Unicode標準中U + n表示法的定義。)

從U + 0000到U + FFFF的字符集有時稱爲 作爲基本多語言平面(BMP)。代碼點 大於U + FFFF的字符稱爲補充字符。 Java平臺在char數組和String和StringBuffer類中使用UTF-16表示。在此表示中,補充 字符表示爲一對char值,第一個來自 高代表範圍,(\ uD800- \ uDBFF),第二個來自 低代理範圍(\ uDC00-\ uDFFF )。

char值,因此,表示基本多語種平面(BMP) 碼分,其中所述替代的編碼點,或 UTF-16編碼的代碼單元。一個int值表示所有的Unicode代碼點,包括補充代碼點的 。 int的低位(最低位)210 用於表示Unicode代碼點,上位(最高位)11位必須爲零。除非另有說明, 關於增補字符和替代 char值的行爲如下:

  • 只接受一個char值無法支持增補字符的方法。他們將代理 範圍內的char值視爲未定義的字符。例如, Character.isLetter('\ uD840')返回false,即使此字符串中的任何低代理值後面的該特定 值將代表一個字母。
  • 接受int值的方法支持所有Unicode字符,包括補充字符。例如, Character.isLetter(0x2F81A)返回true,因爲代碼點值 表示一個字母(CJK表意文字)。