ED A0 80 ED B0 80是一个有效的UTF-8字节序列吗?

java.nio.charset.Charset.forName(“utf8”)。decode解码一个字节序列

ED A0 80 ED B0 80 

进入Unicode代码点:

  U+10000 

java.nio.charset.Charset.forName(“utf8”)。decode也解码一个字节序列

  F0 90 80 80 

进入Unicode代码点:

  U+10000 

这由以下代码validation。

现在这似乎告诉我UTF-8编码方案将ED A0 80 ED B0 80F0 90 80 80解码为相同的unicode代码点。

但是,如果我访问https://www.google.com/search?query=%ED%A0%80%ED%B0%80 ,

我可以看到它明显不同于页面https://www.google.com/search?query=%F0%90%80%80

由于谷歌搜索使用的是UTF-8编码方案(如果我错了,请纠正我),

这表明UTF-8不能将ED A0 80 ED B0 80F0 90 80 80解码为相同的unicode码点。

所以基本上我想知道,按官方标准,UTF-8应该将ED A0 80 ED B0 80字节序列解码为Unicode代码点U + 10000吗?

代码

 public class Test { public static void main(String args[]) { java.nio.ByteBuffer bb = java.nio.ByteBuffer.wrap(new byte[] { (byte) 0xED, (byte) 0xA0, (byte) 0x80, (byte) 0xED, (byte) 0xB0, (byte) 0x80 }); java.nio.CharBuffer cb = java.nio.charset.Charset.forName("utf8").decode(bb); for (int x = 0, xx = cb.limit(); x < xx; ++x) { System.out.println(Integer.toHexString(cb.get(x))); } System.out.println(); bb = java.nio.ByteBuffer.wrap(new byte[] { (byte) 0xF0, (byte) 0x90, (byte) 0x80, (byte) 0x80 }); cb = java.nio.charset.Charset.forName("utf8").decode(bb); for (int x = 0, xx = cb.limit(); x < xx; ++x) { System.out.println(Integer.toHexString(cb.get(x))); } } } 

ED A0 80 ED B0 80是UTF-16代理对D800 DC00的UTF-8编码。 在UTF-8中不允许这样做:

但是,D800和DFFF之间的UCS-2值对(Unicode术语中的代理对)……需要特殊处理: 必须撤消UTF-16转换 ,产生UCS-4字符,然后如上所述进行转换。

但是,这种编码用于CESU-8和Java的“Modified UTF-8”。

由于谷歌搜索使用的是UTF-8编码方案(如果我错了,请纠正我),

基于搜索框,Google似乎正在使用某种编码自动检测function。 如果你传递F0 90 80 80 ,它是有效的UTF-8,它会将其解释为UTF-8( 𐀀 )。 如果你传递ED A0 80 ED B0 80 ,这是无效的UTF-8,它会将其解释为windows-1252 ( í €í°€ )。

Java的UTF8实际上是CESU-8的变种。 第一种情况是使用以UTF8“style”编码的代理对。

 F0 90 80 80 

解码为U+10000 ,或LINEAR B SYLLABLE B008 A

 ED A0 80 ED B0 80 

解码为U+d800 U+dc00