我一直认为java使用UTF-16
在内部对其字符进行编码。事实证明,它使用u+xxxx
格式来表示字符代码,并使用16位来存储char
。
但有时UTF-16
需要超过2个字节。在这种情况下,java需要2个char
来代表1 UTF-16
个字符。
旁注:这让我想知道是否更正确的说“java只支持Unicode字符集,并使用16位单元格存储字符”。
问题:第一个char
是否提供了一些方法来确定是使用了第二个char
,还是2个属于一起?
答案 0 :(得分:6)
是的,UTF-16是在Unicode扩展时将Unicode 1.0的65536代码点限制传递到今天的1114112代码点限制时发明的。
这使它能够支持整个通用字符集,同时保持与UCS-2的兼容性;所有Unicode字符的过时编码为双字节单位,因为它无法在Unicode 2.0或更高版本中对所有Unicode字符进行编码,因此已过时。
第一个char是否提供了一些方法来确定是否使用了第二个char,或者2是否属于一个?
是的,在UTF-16中,两个字节的单位是:
0xD800
和0xDBFF
之间,isHighSurrogate
将返回true
。0xDC00
和0xDFFF
之间,isLowSurrogate
将返回true
。非代理地图直接使用相同代码点的BMP字符。
代理人结合起来代表星体平面人物:
在Java中,您可以首先使用代码点检查isBmpCodePoint
上的int
。如果这是真的,那么你可以将其转换为char
以获得编码它的单个UTF-16单元。否则,您可以致电highSurrogate
获取第一个char
和lowSurrogate
以获得第二个。
与isBmpCodePoint
一样,您可以使用charCount
返回1
表示BMP字符,2
表示您需要代理。如果您要创建一个包含1
或2
个字符的数组来保存该值,这将非常有用。
由于代理代码点永远不会被分配字符,这意味着整个通用字符集的编码是明确的。
它也是自我纠正,流中的错误可以被隔离,而不是导致所有其他字符被误读。例如。如果我们找到一个孤立的低代理,我们知道该位是错误的,但仍然可以读取流的其余部分。
一些完整的例子,但我不是太热了Java(另一方面,我知道的是Unicode,这是我用来回答这个问题的知识),所以如果有人发现了一个n00b Java错误,但我认为我得到了Unicode知识部分是正确的,请继续相应地编辑这篇文章:
""
是一个带有单个Unicode字符的字符串,U+10300
是旧斜体字母的一个字母。在大多数情况下,这些“Astral Planes”角色因为半开玩笑而被称为相对模糊,因为Unicode联盟试图尽可能地使用它们而不会超出易于使用的BMP(基本多语言平面; { {1}}至U+0000
,但有时列为“U+FFFF
至U+0000
U+FFFD
和U+FFFE
均为非字符,不应使用在大多数情况下)。
(如果你正在尝试这个,那么直接使用U+FFFF
的那些将取决于你的文本编辑器应对它的程度)。
如果您检查,您将获得
"".length
,因为2
会为您提供UTF-16编码单位的数量,而不是字符数。
length
应该返回new StringBuilder().appendCodePoint(0x10300).toString() == ""
。
true
将返回Character.charCount(0x10300)
,因为我们需要两个UTF-16 2
来对其进行编码。 char
将返回Character.isBmpCodePoint(0x10300)
。
false
将返回Character.codePointAt("", 0)
66304
,因为当它看到高代理时,它会在计算中读取以下低代理值。
0x10300
是正确的,因为那些是高和低代理人,角色应该被拆分成UTF-16编码。
同样Character.highSurrogate(0x10300) == 0xD800 && Character.lowSurrogate(0x10300) == 0xDF00
因为"".charAt(0) == 0xD800 && "".charAt(1) == 0xDF00
处理的是UTF-16单位,而不是Unicode字符。
使用相同的符号charAt
为两个代理人使用转义符。