UTF-16 分成 2 个字符
UTF-16 split in 2 chars
我一直认为 java 使用 UTF-16
对其字符进行内部编码。它使用 u+xxxx
格式来表示字符代码以及它使用 16 位来存储 char
.
的事实证实了这一点。
但有时UTF-16
需要2个字节以上那样的话java需要2char
来表示1UTF-16
字符.
旁注:这让我想知道说 "java just supports the Unicode character set, and uses 16-bit cells to store characters".
是否更正确
问题:第一个 char
是否提供了一些方法来确定第二个 char
被使用,或者两者属于一起?
是的,UTF-16 是在 Unicode 将 Unicode 1.0 的 65536 个代码点限制扩展到今天的 1114112 个代码点限制时发明的。
这允许它支持整个通用字符集,同时保持与 UCS-2 的兼容性;将所有 Unicode 字符作为双字节单元的过时编码,正是因为它无法在 Unicode 2.0 或更高版本中对所有 Unicode 字符进行编码。
Does the first char offer some method to determine that a second char is used, or that the 2 belong together?
是的,在 UTF-16 中,两个字节的单位是:
- 高代理项,必须始终跟有低代理项。在
0xD800
和 0xDBFF
之间,isHighSurrogate
将 return true
.
- 必须始终跟随高代理项的低代理项。在
0xDC00
和 0xDFFF
之间,isLowSurrogate
将 return true
.
- 非代理人。
非代理映射直接与一个相同码位的BMP字符。
代理人组合起来代表星界角色:
- 从代码点中减去 0x010000。
- 将前 10 位添加到 0xD800 以获得高代理项。
- 将低 10 位添加到 0xDC00 以获得低代理项。
在 Java 中,您可以通过首先使用代码点检查 int
上的 isBmpCodePoint
来执行此操作。如果这是真的,那么您可以将其转换为 char
以获得对其进行编码的单个 UTF-16 单元。否则,您可以调用 highSurrogate
获取第一个 char
并调用 lowSurrogate
获取第二个。
和 isBmpCodePoint
一样,您可以使用 charCount
,其中 returns 1
用于 BMP 字符,2
如果您需要代理。如果您要创建 1
或 2
个字符的数组来保存值,这将很有用。
由于永远不会为代理代码点分配字符,这意味着编码对于整个通用字符集都是明确的。
它也是自我纠正的,可以隔离流中的错误,而不是导致所有其他字符被误读。例如。如果我们找到一个孤立的低代理项,我们知道该位是错误的,但仍然可以读取流的其余部分。
一些完整的示例,但我在 Java 中不太热(另一方面,我很了解 Unicode,这就是我用来回答这个问题的知识),所以如果有人发现 n00b Java 错误,但认为我的 Unicode 知识部分正确,请继续并相应地编辑此 post:
""
是一个带有单个 Unicode 字符的字符串,U+10300
是旧斜体字母表中的一个字母。在大多数情况下,这些半开玩笑地称为 "Astral Planes" 的字符相对晦涩,因为 Unicode 联盟试图在不超出更易于使用的 BMP(基本多语言平面;基本多语言平面; U+0000
到 U+FFFF
,尽管有时列为“U+0000
到 U+FFFD
,因为 U+FFFE
和 U+FFFF
都是非字符,不应该大多数情况下使用)。
(如果你正在试验这个,那么直接使用 </code> 的那些将取决于你的文本编辑器处理它的能力)。</p>
<p>如果你检查 <code>"".length
你会得到 2
因为 length
给你的是 UTF-16 编码单元的数量,而不是字符的数量。
new StringBuilder().appendCodePoint(0x10300).toString() == ""
应该 return true
.
Character.charCount(0x10300)
将 return 2
因为我们需要两个 UTF-16 char
来编码它。 Character.isBmpCodePoint(0x10300)
将 return false
.
Character.codePointAt("", 0)
将 return 66304
即 0x10300
,因为当它看到高代理时,它包括在计算中读取以下低代理。
Character.highSurrogate(0x10300) == 0xD800 && Character.lowSurrogate(0x10300) == 0xDF00
是正确的,因为这些是应该将字符拆分成以 UTF-16 编码的高位和低位代理项。
同样 "".charAt(0) == 0xD800 && "".charAt(1) == 0xDF00
因为 charAt
处理 UTF-16 单位,而不是 Unicode 字符。
出于同样的原因 "" == "\uD800\uDF00"
对两个代理项使用转义符。
我一直认为 java 使用 UTF-16
对其字符进行内部编码。它使用 u+xxxx
格式来表示字符代码以及它使用 16 位来存储 char
.
但有时UTF-16
需要2个字节以上那样的话java需要2char
来表示1UTF-16
字符.
旁注:这让我想知道说 "java just supports the Unicode character set, and uses 16-bit cells to store characters".
是否更正确问题:第一个 char
是否提供了一些方法来确定第二个 char
被使用,或者两者属于一起?
是的,UTF-16 是在 Unicode 将 Unicode 1.0 的 65536 个代码点限制扩展到今天的 1114112 个代码点限制时发明的。
这允许它支持整个通用字符集,同时保持与 UCS-2 的兼容性;将所有 Unicode 字符作为双字节单元的过时编码,正是因为它无法在 Unicode 2.0 或更高版本中对所有 Unicode 字符进行编码。
Does the first char offer some method to determine that a second char is used, or that the 2 belong together?
是的,在 UTF-16 中,两个字节的单位是:
- 高代理项,必须始终跟有低代理项。在
0xD800
和0xDBFF
之间,isHighSurrogate
将 returntrue
. - 必须始终跟随高代理项的低代理项。在
0xDC00
和0xDFFF
之间,isLowSurrogate
将 returntrue
. - 非代理人。
非代理映射直接与一个相同码位的BMP字符。
代理人组合起来代表星界角色:
- 从代码点中减去 0x010000。
- 将前 10 位添加到 0xD800 以获得高代理项。
- 将低 10 位添加到 0xDC00 以获得低代理项。
在 Java 中,您可以通过首先使用代码点检查 int
上的 isBmpCodePoint
来执行此操作。如果这是真的,那么您可以将其转换为 char
以获得对其进行编码的单个 UTF-16 单元。否则,您可以调用 highSurrogate
获取第一个 char
并调用 lowSurrogate
获取第二个。
和 isBmpCodePoint
一样,您可以使用 charCount
,其中 returns 1
用于 BMP 字符,2
如果您需要代理。如果您要创建 1
或 2
个字符的数组来保存值,这将很有用。
由于永远不会为代理代码点分配字符,这意味着编码对于整个通用字符集都是明确的。
它也是自我纠正的,可以隔离流中的错误,而不是导致所有其他字符被误读。例如。如果我们找到一个孤立的低代理项,我们知道该位是错误的,但仍然可以读取流的其余部分。
一些完整的示例,但我在 Java 中不太热(另一方面,我很了解 Unicode,这就是我用来回答这个问题的知识),所以如果有人发现 n00b Java 错误,但认为我的 Unicode 知识部分正确,请继续并相应地编辑此 post:
""
是一个带有单个 Unicode 字符的字符串,U+10300
是旧斜体字母表中的一个字母。在大多数情况下,这些半开玩笑地称为 "Astral Planes" 的字符相对晦涩,因为 Unicode 联盟试图在不超出更易于使用的 BMP(基本多语言平面;基本多语言平面; U+0000
到 U+FFFF
,尽管有时列为“U+0000
到 U+FFFD
,因为 U+FFFE
和 U+FFFF
都是非字符,不应该大多数情况下使用)。
(如果你正在试验这个,那么直接使用 </code> 的那些将取决于你的文本编辑器处理它的能力)。</p>
<p>如果你检查 <code>"".length
你会得到 2
因为 length
给你的是 UTF-16 编码单元的数量,而不是字符的数量。
new StringBuilder().appendCodePoint(0x10300).toString() == ""
应该 return true
.
Character.charCount(0x10300)
将 return 2
因为我们需要两个 UTF-16 char
来编码它。 Character.isBmpCodePoint(0x10300)
将 return false
.
Character.codePointAt("", 0)
将 return 66304
即 0x10300
,因为当它看到高代理时,它包括在计算中读取以下低代理。
Character.highSurrogate(0x10300) == 0xD800 && Character.lowSurrogate(0x10300) == 0xDF00
是正确的,因为这些是应该将字符拆分成以 UTF-16 编码的高位和低位代理项。
同样 "".charAt(0) == 0xD800 && "".charAt(1) == 0xDF00
因为 charAt
处理 UTF-16 单位,而不是 Unicode 字符。
出于同样的原因 "" == "\uD800\uDF00"
对两个代理项使用转义符。