【问题标题】:How does Java store UTF-16 characters in its 16-bit char type?Java 如何在其 16 位 char 类型中存储 UTF-16 字符?
【发布时间】:2012-10-28 19:57:00
【问题描述】:

根据Java SE 7 Specification,Java 使用Unicode UTF-16 标准来表示字符。 当将String 想象为一个由 16 位变量组成的简单数组时,每个变量都包含一个字符,生活很简单。

不幸的是,有些代码点 16 位根本不够用(我相信它是所有 Unicode 字符的 16/17)。所以在String 中,这不会造成直接问题,因为当想要使用额外的两个字节 存储其中一个~1.048.576 个字符时,只需在String 中的两个数组位置即可用过。

这对Strings 有效,不会造成任何直接 问题,因为总是可以有额外的两个字节。虽然当涉及到单个变量时,与 UTF-16 编码相比,它具有 16 位的固定长度,但如何存储这些字符,尤其是 Java 是如何做到的它的2 字节“char”类型

【问题讨论】:

  • 请不要滥用反引号。它们仅用于代码
  • 它没有......如果它可以存储一个点,他们会称之为'字符':) String[index] 可能是一个无效字符。更多信息在utf8everywhere.org
  • @KerrekSB 好吧,我一直用它们来强调或强调似乎最重要或具有高识别价值的单词或短语。但是感谢您让我正确,我会在未来更加注意。
  • @Kierrow:您可以使用斜体和粗体来表示正常和特别强调。对于大多数 SO 帖子来说,这应该足够了! :-)

标签: java variables unicode encoding utf-16


【解决方案1】:

答案在the javadoc

char 数据类型(因此是 Character 对象的值 封装)基于原始的 Unicode 规范,其中 将字符定义为固定宽度的 16 位实体。统一码 此后标准已更改为允许其 表示需要超过 16 位。

法码范围 点现在是 U+0000 到 U+10FFFF,称为 Unicode 标量值。 (参考 Unicode 标准中 U+n 符号的定义。) 从 U+0000 到 U+FFFF 的字符集有时被称为 作为基本多语言平面(BMP)。代码点的字符 大于 U+FFFF 的称为补充字符。爪哇 2 平台在 char 数组和 String 和 StringBuffer 类。在此表示中,补充 字符表示为一对 char 值,第一个来自 高代理范围,(\uD800-\uDBFF),从第二个 低代理范围 (\uDC00-\uDFFF)。

一个 char 值,因此, 表示基本多语言平面 (BMP) 代码点,包括 代理代码点,或 UTF-16 编码的代码单元。一个整数 value 代表所有 Unicode 码位,包括补充码 点。 int 的低(最低有效)21 位用于 表示 Unicode 代码点和高(最高有效)11 位 必须为零。

除非另有说明,否则关于 补充字符和代理字符值如下: 只接受 char 值的方法不支持补充 人物。他们将代理范围中的 char 值视为 未定义的字符。例如,Character.isLetter('\uD840') 返回 false,即使此特定值后跟任何 字符串中的低代理值将代表一个字母。方法 接受 int 值的支持所有 Unicode 字符,包括 补充字符。例如,Character.isLetter(0x2F81A) 返回 true,因为代码点值表示一个字母(CJK 表意文字)。在 Java SE API 文档中,Unicode 代码点是 用于 U+0000 到 U+10FFFF 范围内的字符值, Unicode 代码单元用于 16 位 char 值,这些值是代码 UTF-16 编码的单位。有关 Unicode 的更多信息 术语,请参阅 Unicode 词汇表。

简单地说:

  • char 规则的 16 位是为旧版本的 Unicode 标准设计的
  • 有时您需要两个字符来表示不在基本多语言平面中的 unicode 符文(代码点)。这种“有效”是因为您不经常使用字符,尤其是在处理 BMP 之外的 unicode 符文时。

更简单的说:

  • java char 不代表 Unicode 代码点(嗯,并非总是如此)。

顺便说一句,可以指出的是,Unicode 的演变超越了 BMP,使得 UTF-16 在全球范围内变得无关紧要,因为 UTF-16 甚至不支持固定的字节字符比率。这就是为什么更现代的语言基于 UTF-8。这个manifesto 有助于理解它。

【讨论】:

  • int ch 存储补充字符,我如何将其存储为字符串的一部分? write(int ch) 可用于将该字符写入另一个外部源。
【解决方案2】:

基本上,字符串存储一系列 UTF-16 代码单元...这与存储 Unicode 代码点序列不同。

当需要基本多语言平面之外的字符时,它会占用String 内的两个 UTF-16 代码单元。

大多数 String 操作 - length()charAtsubstring() 等处理 UTF-16 代码单元的数量。然而,像codePointAt() 这样的操作将处理完整的 Unicode 代码点……尽管索引仍然以 UTF-16 代码单元表示。

编辑:如果您想将非 BMP 代码点存储在单个 char 中,那么您基本上就不走运了。这就像想在 byte 变量中存储超过 256 个不同的值......它只是不起作用。按照在其他地方表示代码点的约定(例如在String 中),最好只使用int 变量。

【讨论】:

  • 有趣且重要,但问题似乎更多地集中在单个 chars 上,而不是字符串操作(参见问题的最后一句)。
猜你喜欢
  • 2011-12-29
  • 2013-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-22
  • 2012-01-09
相关资源
最近更新 更多