2012-01-12 28 views
10

java.nio.charset.Charset.forName("utf8").decode giải mã một chuỗi byte củaED A0 80 ED B0 80 có phải là một chuỗi byte UTF-8 hợp lệ không?

ED A0 80 ED B0 80 

vào điểm mã Unicode:

U+10000 

java.nio.charset.Charset.forName("utf8").decode cũng giải mã một chuỗi byte của

F0 90 80 80 

vào điểm mã Unicode:

U+10000 

Điều này được xác minh bởi code below.

Bây giờ điều này dường như nói với tôi rằng lược đồ mã hóa UTF-8 sẽ giải mã ED A0 80 ED B0 80F0 90 80 80 vào cùng một điểm mã hóa unicode.

Tuy nhiên, nếu tôi đến thăm https://www.google.com/search?query=%ED%A0%80%ED%B0%80,

tôi có thể thấy rằng nó rõ ràng là khác nhau từ trang https://www.google.com/search?query=%F0%90%80%80

Kể từ khi Google Search đang sử dụng chương trình mã UTF-8 (chính xác cho tôi nếu tôi sai) là tốt,

Điều này cho thấy rằng UTF-8 không giải mã ED A0 80 ED B0 80F0 90 80 80 vào cùng một điểm mã unicode (s). Vì vậy, về cơ bản tôi đã tự hỏi, theo tiêu chuẩn chính thức, nên UTF-8 giải mã trình tự byte ED A0 80 ED B0 80 vào mã Unicode Unicode U + 10000 không? Không.

:

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

Tôi nhận được hai chuỗi rất khác nhau khi tôi UTF-8 giải mã trong LINQPad (C#). Cái sau thực sự dẫn đến một "cặp thay thế không hợp lệ" khi truy cập nhân vật khôn ngoan được cố gắng. –

+0

@pst Bạn đang nói rằng thuật toán giải mã mà Java sử dụng là thiếu sót? – Pacerier

+2

@Pacerier: tốt, việc thực thi Java UTF-8 là [được biết đến là thiếu sót] (https://en.wikipedia.org/wiki/CESU-8). –

Trả lời

11

ED A0 80 ED B0 80 là mã hóa UTF-8 của cặp thay thế UTF-16 D800 DC00. Đây là KHÔNG phép trong UTF-8:

Tuy nhiên, cặp UCS 2 giá trị giữa D800 và DFFF (cặp thay thế trong Unicode cách nói) ... cần điều trị đặc biệt: việc chuyển đổi UTF-16 phải được hoàn tác, cho ra một ký tự UCS-4 sau đó được chuyển đổi như trên.

Tuy nhiên, chẳng hạn một mã hóa được sử dụng trong CESU-8 và Java của "Modified UTF-8".

Kể từ khi Google Search đang sử dụng chương trình mã UTF-8 (đúng cho tôi nếu tôi sai) là tốt,

Nó xuất hiện, căn cứ vào hộp tìm kiếm, mà Google đang sử dụng một số loại mã hóa tự động phát hiện. Nếu bạn vượt qua nó F0 90 80 80, là hợp lệ UTF-8, nó diễn giải nó như là UTF-8 (). Nếu bạn vượt qua nó ED A0 80 ED B0 80, không hợp lệ UTF-8, nó diễn giải nó là windows-1252 (í�€í°€).

+0

Tôi không có ý tưởng nó đã được sửa đổi theo cách "không khuyến khích ... để trao đổi thông tin mở" :( –

+0

@ dan04 Ok để xác nhận những gì bạn đã nói, bạn đang gợi ý rằng 'java.nio.charset.Charset.forName ("utf8") decode' nên ném một lỗi (mà nó đã không) khi chúng ta ăn nó với 'ED A0 80 ED B0 80'? – Pacerier

0
F0 90 80 80 

giải mã như U+10000, hoặc LINEAR B SYLLABLE B008 A.

ED A0 80 ED B0 80 

giải mã là U+d800 U+dc00.

1

UTF8 của Java thực sự là một biến thể CESU-8. Trường hợp đầu tiên là sử dụng cặp thay thế được mã hóa theo kiểu "UTF8".

Các vấn đề liên quan