2012-01-12 13 views
10

java.nio.charset.Charset.forName("utf8").decode dekoduje sekwencja bajtówCzy ED A0 80 ED B0 80 jest prawidłową sekwencją bajtów UTF-8?

ED A0 80 ED B0 80 

do kodowy Unicode:

U+10000 

java.nio.charset.Charset.forName("utf8").decode dekoduje również sekwencję bajtów

F0 90 80 80 

do kodowy Unicode:

U+10000 

Zostało to zweryfikowane przez code below.

Teraz wydaje mi się, że schemat kodowania UTF-8 dekoduje ED A0 80 ED B0 80 i F0 90 80 80 w ten sam kodek kodu Unicode.

Jednakże, jeśli mogę odwiedzić https://www.google.com/search?query=%ED%A0%80%ED%B0%80,

widzę, że jest to wyraźnie różni się od strony https://www.google.com/search?query=%F0%90%80%80

Od wyszukiwarce Google przy użyciu schematu kodowania UTF-8 (poprawcie mnie jeśli się mylę) również,

Sugeruje to, że kodowanie UTF-8 nie dekoduje ED A0 80 ED B0 80 i F0 90 80 80 w ten sam kod (y) kodu Unicode.

Więc w zasadzie zastanawiałem się, o standardzie oficjalnej należy UTF-8 dekodowania ED A0 80 ED B0 80 sekwencję bajtów na punkt kodowy Unicode U + 10000?

Kod:

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

Otrzymuję dwa bardzo różne ciągi, gdy UTF-8 dekodowane w LINQPad (C#). Ten ostatni w rzeczywistości daje "nieprawidłową parę zastępczą", gdy próbuje się uzyskać dostęp do postaci. –

+0

@pst Czy mówisz, że algorytm dekodowania używany przez Javę jest wadliwy? – Pacerier

+2

@Pacerier: Cóż, implementacja Java UTF-8 jest [znana jest wadą] (https://en.wikipedia.org/wiki/CESU-8). –

Odpowiedz

11

ED A0 80 ED B0 80 to kodowanie UTF-8 pary surogatów UTF-16 D800 DC00. To NIE dozwolone w UTF-8:

Jednak pary UCS-2 wartości między D800 i DFFF (zastępcze par w żargonie Unicode) ... potrzebują specjalnego traktowania: transformacji UTF-16 musi należy cofnąć, uzyskując znak UCS-4, który jest następnie przekształcony jak wyżej.

Jednakże takie kodowanie jest stosowane w CESU-8 i Java "Zmodyfikowany UTF-8".

Od wyszukiwarce Google jest przy użyciu schematu kodowania UTF-8 (poprawcie mnie jeśli się mylę), jak również,

Wydaje się, na podstawie polu wyszukiwania Google jest przy użyciu pewnego rodzaju automatycznego wykrywania kodowania. Jeśli go podasz F0 90 80 80, który jest prawidłowym UTF-8, interpretuje go jako UTF-8 (). Jeśli go podasz ED A0 80 ED B0 80, który jest nieprawidłowy UTF-8, interpretuje go jako windows-1252 (í�€í°€).

+0

Nie miałem pojęcia, że ​​został zmodyfikowany w sposób "niezalecany ... dla otwartej wymiany informacji" :( –

+0

@ dan04 OK, aby potwierdzić, co powiedziałeś, sugerujesz, że 'java.nio.charset.Charset.forName ("utf8") .decode "powinien dać błąd (który nie zrobił), gdy będziemy go podawać za pomocą' ED A0 80 ED B0 80'? – Pacerier

0
F0 90 80 80 

dekoduje jako U+10000 lub LINEAR B SYLLABLE B008 A.

ED A0 80 ED B0 80 

dekoduje jako U+d800 U+dc00.

1

Java's UTF8 jest naprawdę wariantem CESU-8. Pierwszy przypadek to użycie zastępczych par zakodowanych w "stylu" UTF8.

Powiązane problemy