2012-01-12 12 views
10

java.nio.charset.Charset.forName("utf8").decode decodifica una sequenza di byte diED A0 80 ED B0 80 una sequenza di byte UTF-8 valida?

ED A0 80 ED B0 80 

nel codepoint Unicode:

U+10000 

java.nio.charset.Charset.forName("utf8").decode decodifica anche una sequenza di byte di

F0 90 80 80 

nel codepoint Unicode:

U+10000 

Questo è verificato dal code below.

Ora sembra dirmi che lo schema di codifica UTF-8 decodificherà ED A0 80 ED B0 80 e F0 90 80 80 nello stesso punto di codice unicode.

Tuttavia, se visito https://www.google.com/search?query=%ED%A0%80%ED%B0%80,

posso vedere che è chiaramente diversa dalla pagina https://www.google.com/search?query=%F0%90%80%80

Poiché la ricerca di Google sta usando schema di codifica UTF-8 (correggetemi se sbaglio),

Ciò suggerisce che l'UTF-8 non decodifica ED A0 80 ED B0 80 e F0 90 80 80 negli stessi codici unicode (s).

Quindi, in pratica mi chiedevo, per lo standard ufficiale, dovrebbe UTF-8 decodifica ED A0 80 ED B0 80 sequenza di byte in Unicode codepoint U + 10000?

Codice:

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

Ottengo due stringhe molto diverse quando UTF-8 lo decodifica in LINQPad (C#). Quest'ultimo in realtà si traduce in una "coppia surrogata non valida" quando si tenta l'accesso al carattere. –

+0

@ pst Stai dicendo che l'algoritmo di decodifica utilizzato da Java è difettoso? – Pacerier

+2

@Pacerier: beh, l'implementazione Java UTF-8 è [nota per essere difettosa] (https://en.wikipedia.org/wiki/CESU-8). –

risposta

11

ED A0 80 ED B0 80 è la codifica UTF-8 della coppia sostitutiva UTF-16 D800 DC00. Questo è NON accettati in UTF-8:

Tuttavia, coppie di UCS-2 valori tra D800 e DFFF (coppie di surrogati in Unicode gergo) ... bisogno di un trattamento speciale: UTF-16 trasformazione devono essere annullato, ottenendo un carattere UCS-4 che è quindi trasformato come sopra.

Tuttavia, una tale codifica è utilizzato in CESU-8 e di Java "UTF-8 modificato".

Dal momento che la ricerca di Google sta usando schema di codifica UTF-8 (correggetemi se sbaglio), nonché,

Sembra, in base alla casella di ricerca, che Google sta usando qualche tipo di rilevamento automatico della codifica. Se lo passi F0 90 80 80, che è UTF-8 valido, lo interpreta come UTF-8 (). Se lo passi ED A0 80 ED B0 80, che non è UTF-8 valido, lo interpreta come windows-1252 (í�€í°€).

+0

Non avevo idea che fosse modificato in un modo "sconsigliato ... per lo scambio di informazioni aperto" :( –

+0

@ dan04 Ok per confermare quello che hai detto, stai suggerendo che 'java.nio.charset.Charset.forName ("utf8"). decode' dovrebbe generare un errore (che non ha) quando lo alimentiamo con 'ED A0 80 ED B0 80'? – Pacerier

0
F0 90 80 80 

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

ED A0 80 ED B0 80 

decodifica come U+d800 U+dc00.

1

Java UTF8 è davvero una variante CESU-8. Il primo caso utilizza coppie surrogate codificate in "stile" UTF8.

Problemi correlati