6

Dường như có sự mơ hồ giữa các Dấu đơn hàng Byte được sử dụng cho UTF16-LE và UTF-32LE. Đặc biệt, hãy xem xét một tập tin có chứa 8 byte sau:Unicode BOM cho UTF-16LE và UTF32-LE

FF FE 00 00 00 00 00 00 

Làm thế nào tôi có thể nói nếu tập tin này chứa:

  1. Các UTF16-LE BOM (FF FE) tiếp theo là 3 ký tự null; hoặc
  2. UTF32-LE BOM (FF FE 00 00) theo sau là một ký tự null?

Unicode BOM được mô tả ở đây: http://unicode.org/faq/utf_bom.html#bom4 nhưng không có thảo luận về sự mơ hồ này. Tui bỏ lỡ điều gì vậy?

Trả lời

10

Như tên cho thấy, BOM chỉ cho bạn biết thứ tự byte , không phải mã hóa. Bạn phải biết mã hóa là gì trước tiên, sau đó bạn có thể sử dụng BOM để xác định xem các byte ít nhất hoặc quan trọng nhất là đầu tiên cho chuỗi multibyte.

Một tác dụng phụ may mắn của BOM là đôi khi bạn có thể sử dụng nó để đoán mã hóa nếu bạn không biết, nhưng đó không phải là thứ được thiết kế và không thể thay thế để gửi mã hóa thích hợp thông tin.

10

Nó rõ ràng. FF FE dành cho UTF-16LE và FF FE 00 00 biểu thị UTF-32LE. Không có lý do gì để nghĩ rằng FF FE 00 00 có thể là UTF-16LE vì UTF được thiết kế cho văn bản và người dùng không nên sử dụng các ký tự NUL trong văn bản của họ. Sau khi tất cả, khi là lần cuối cùng bạn mở một trình soạn thảo hex và chèn một vài byte 00 vào một tài liệu văn bản?^_^

+4

Ký tự rỗng có thể là một phần của giao thức bậc cao được mã hóa trong văn bản. Unicode không thực sự quan tâm đến những điểm mã được sử dụng trong văn bản và U + 0000 chỉ là hợp lệ như U + 0041. – Joey

+2

Đọc một giao thức bậc cao hơn, lý thuyết này mâu thuẫn với thiết lập câu hỏi trong đó mã hóa phải được đoán. Nếu bạn đang đọc một giao thức, bạn không đoán mã hóa. – u0b34a0f6ae

+1

Để đặt nó theo một cách khác, nó không * không thể * để có một U + 0000 ở đầu của một tập tin, nhưng nó * cực kỳ hiếm *. Nếu đây là một khả năng cho dữ liệu bạn đang đọc thì bạn không nên dựa vào một BOM để phát hiện định dạng. –

1

Tôi đã gặp phải vấn đề tương tự như Edward. Tôi đồng ý với Dustin, thông thường một người sẽ không sử dụng các ký tự rỗng trong các tệp văn bản.

Tuy nhiên tôi đã tạo một tệp chứa tất cả các ký tự unicode. Trước tiên tôi đã sử dụng mã hóa utf-32le, sau đó mã hóa utf-32be, mã utf-16le và mã hóa utf-16be cũng như mã hóa utf-8.

Khi cố gắng mã hóa lại các tệp thành utf-8, tôi muốn so sánh kết quả với tệp utf-8 hiện có. Vì ký tự đầu tiên trong tệp của tôi sau BOM là ký tự rỗng, tôi không thể phát hiện thành công tệp với utf-16le BOM, nó hiển thị dưới dạng utf-32le BOM, vì các byte xuất hiện chính xác như Edward đã mô tả. Ký tự đầu tiên sau BOM FFFE là 0000, nhưng phát hiện BOM tìm thấy một FFFE0000 BOM và như vậy, phát hiện utf-32le thay vì utf-16le, theo đó ký tự 0000 đầu tiên của tôi đã bị đánh cắp và lấy làm một phần của BOM.

Vì vậy, người ta không bao giờ nên sử dụng ký tự null làm ký tự đầu tiên của tệp được mã hóa với utf-16 chút endian, vì nó sẽ làm cho utf-16le và utf-32le BOM mơ hồ.

Để giải quyết vấn đề của mình, tôi sẽ trao đổi ký tự đầu tiên và ký tự thứ hai. :-)

+0

Nếu bạn dựa vào BOM một mình để phát hiện mã hóa, thì bạn cần xem xét nhiều byte hơn chỉ là BOM để giải quyết sự mơ hồ UTF-16/32. Kiểm tra UTF-16LE đầu tiên, và nếu phát hiện sau đó kiểm tra nếu N * 2 byte tiếp theo là hợp lệ UTF-16LE, trong đó N là một số hợp lý. Nếu không hợp lệ UTF-16LE, hãy bắt đầu lại và giả định UTF-32LE. U + 0000 phải là điểm duy nhất mơ hồ, và không nên có nhiều null ở đầu tệp. Tại một thời điểm nào đó, phải có một điểm ngắt và nếu bạn vẫn không thể giải quyết sự mơ hồ, hãy nhắc người dùng hoặc không xử lý lỗi. –

+0

Có nghĩa là, nếu phát hiện ra một BOM utf-32le, một trong những đầu tiên nên kiểm tra xem nó thực sự là một UOM utf-16le với một U + 0000 sau codepoint. Nếu có rất nhiều từ, điều này có thể giúp đỡ, có thể phát hiện cũng thay thế. Nhưng nếu có một từ chỉ xem, điều này có thể khó. Nhưng tôi đồng ý, khi kiểm tra các codepoints utf-32 hợp lệ, có thể bạn sẽ tìm thấy các điểm mã ngoài phạm vi tối đa 0x10FFFF nếu nó thực sự là một tệp được mã hóa utf-16. Dù sao chúng tôi cũng khuyên bạn nên đặt một điểm mã khác ngoài U + 0000 làm điểm mã đầu tiên trong tệp được mã hóa utf-16le. – brighty