2010-03-28 139 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表意文字)。