2012-01-12 12 views
10

java.nio.charset.Charset.forName("utf8").decode decodifica una secuencia de bytes de¿ED A0 80 ED B0 80 es una secuencia de bytes UTF-8 válida?

ED A0 80 ED B0 80 

en el punto de código Unicode:

U+10000 

java.nio.charset.Charset.forName("utf8").decode también decodifica una secuencia de bytes de

F0 90 80 80 

en el punto de código Unicode:

U+10000 

Esto se verifica por el code below.

Ahora esto parece indicarme que el esquema de codificación UTF-8 decodificará ED A0 80 ED B0 80 y F0 90 80 80 en el mismo punto de código Unicode.

Sin embargo, si volviese a https://www.google.com/search?query=%ED%A0%80%ED%B0%80,

puedo ver que es claramente diferente de la página https://www.google.com/search?query=%F0%90%80%80

Dado que la búsqueda de Google está usando esquema de codificación UTF-8 (corríjanme si me equivoco) también,

Esto sugiere que el UTF-8 no decodifica ED A0 80 ED B0 80 y F0 90 80 80 en el mismo punto (s) código Unicode.

Así que básicamente me preguntaba, por la norma oficial, debe UTF-8 decodificación ED A0 80 ED B0 80 secuencia de bytes en el punto de código Unicode U + 10000?

Código:

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))); 
     } 
    } 
} 
+0

Obtengo dos cadenas muy diferentes cuando I UTF-8 decodifica eso en LINQPad (C#). El último realmente da como resultado un "par suplente inválido" cuando se intenta el acceso de carácter. –

+0

@pst ¿Está diciendo que el algoritmo de decodificación que utiliza Java es defectuoso? – Pacerier

+2

@Pacerier: bueno, la implementación de Java UTF-8 es [conocida por ser defectuosa] (https://en.wikipedia.org/wiki/CESU-8). –

Respuesta

11

ED A0 80 ED B0 80 es la codificación UTF-8 del par suplente UTF-16 D800 DC00. Esto es NO permitido en UTF-8:

Sin embargo, los pares de UCS-2 valores entre D800 y DFFF (pares suplentes en Unicode jerga) ... necesitan un tratamiento especial: la transformación UTF-16 debe deshazte de, obteniendo un carácter UCS-4 que es entonces transformado como se indica anteriormente.

Sin embargo, una codificación tal se utiliza en CESU-8 y de Java "UTF-8 modificado".

Dado que la búsqueda de Google está utilizando esquema de codificación UTF-8 (corríjanme si me equivoco), así,

Parece, basado en el cuadro de búsqueda, que Google está utilizando algún tipo de la autodetección de codificación. Si lo pasa F0 90 80 80, que es UTF-8 válido, lo interpreta como UTF-8 (). Si lo pasa ED A0 80 ED B0 80, que es UTF-8 no válido, lo interpreta como windows-1252 (í�€í°€).

+0

No tenía idea de que se había modificado de una manera "no recomendada ... para el intercambio de información abierto" :( –

+0

@ dan04 Ok para confirmar lo que ha dicho, está sugiriendo que 'java.nio.charset.Charset.forName ("utf8"). decode' debería arrojar un error (que no fue así) cuando lo alimentamos con 'ED A0 80 ED B0 80'? – Pacerier

0
F0 90 80 80 

decodifica como U+10000 o LINEAR B SYLLABLE B008 A.

ED A0 80 ED B0 80 

decodifica como U+d800 U+dc00.

1

UTF8 de Java es realmente una variante CESU-8. El primer caso es el uso de pares de sustitución codificados en "estilo" UTF8.

Cuestiones relacionadas