对于任何给定的Java字符串s
,我想知道s
表示的字符数组保证是否是有效的UTF-16字符串,例如:
final char[] ch = new char[s.length()];
for (int i = 0; i < ch.length; ++i) {
ch[i] = s.charAt(i);
}
// Is ch guaranteed to be a valid UTF-16 encoded string?
如果没有,那些产生无效UTF-16的简单Java语言测试用例是什么?
编辑:有人将此问题标记为[Is a Java char array always a valid UTF-16 (Big Endian) encoding?的可能副本我只能说,String
和{char[]
之间存在差异{1}}以及为什么前者至少在理论上可以保证后者不能保证其内容的原因。我没有问过关于数组的问题,我问了一个关于String
的问题。
答案 0 :(得分:3)
没有。 String
只是char[]
的无限制包装:
char data[] = {'\uD800', 'b', 'c'}; // Unpaired lead surrogate
String str = new String(data);
要测试格式正确的UTF-16数据的String
或char[]
,您可以使用CharsetEncoder
:
CharsetEncoder encoder = Charset.forName("UTF-16LE").newEncoder();
ByteBuffer bytes = encoder.encode(CharBuffer.wrap(str)); // throws MalformedInputException
答案 1 :(得分:2)
不可以,在程序执行期间,不保证Java String的实例在所有点都包含有效的UTF-16代码单元序列(即16位值)。它也必须以这种方式工作。
这是微不足道的证明。想象一下,您有一系列代码点(通常以32位整数存储的21位数量),您希望将其附加到一个字符串,一次一个字符单元。如果其中一些代码点位于基本多语言平面之上(即,值> 0xFFFF,因此需要超过16位来保存它们),那么当一次添加一个16位代码单元时,您将拥有一个String期间,String只有一个主要的代理,但还没有所需的尾随代理。
换句话说,它更像是一个char-unit缓冲区 - 一个16位值的缓冲区 - 而不是一个合法的UTF-16序列。这确实是String类型的必要方面。
只有在将其转换为特定编码时才会出现问题,因为不匹配,翻转或单独的代理在三种UTF格式中都不合法,因此编码器无法代表它们。