Sự khác biệt giữa UTF-8 và UTF-8 không có BOM là gì?


818

Có gì khác nhau giữa UTF-8 và UTF-8 mà không có BOM ? Cái nào tốt hơn?


77
UTF-8 có thể được tự động phát hiện tốt hơn bởi nội dung so với BOM. Phương pháp rất đơn giản: cố gắng đọc tệp (hoặc một chuỗi) dưới dạng UTF-8 và nếu điều đó thành công, giả sử rằng dữ liệu là UTF-8. Mặt khác, giả sử rằng đó là CP1252 (hoặc mã hóa 8 bit khác). Bất kỳ mã hóa tám bit không UTF-8 nào gần như chắc chắn sẽ chứa các chuỗi không được UTF-8 cho phép. ASCII thuần túy (7 bit) được hiểu là UTF-8, nhưng kết quả cũng đúng theo cách đó.
Tronic

39
Quét các tệp lớn để tìm nội dung UTF-8 cần có thời gian. Một BOM làm cho quá trình này nhanh hơn nhiều. Trong thực tế bạn thường cần phải làm cả hai. Thủ phạm hiện nay là vẫn còn rất nhiều nội dung văn bản không phải là Unicode và tôi vẫn tìm hiểu các công cụ nói rằng họ làm Unicode (ví dụ UTF-8) nhưng phát ra nội dung của họ một bản mã khác.
Jeroen Wiert Pluimers

10
@Tronic Tôi không thực sự nghĩ rằng "tốt hơn" phù hợp trong trường hợp này. Nó phụ thuộc vào môi trường. Nếu bạn chắc chắn rằng tất cả các tệp UTF-8 được đánh dấu bằng BOM hơn là kiểm tra BOM là cách "tốt hơn" , bởi vì nó nhanh hơn và đáng tin cậy hơn.
mg30rg

32
UTF-8 không có BOM. Khi bạn đặt điểm mã U + FEFF khi bắt đầu tệp UTF-8, phải đặc biệt cẩn thận để xử lý. Đây chỉ là một trong những lời nói dối của Microsoft, giống như gọi một mã hóa "Unicode" khi không có điều đó.
tchrist

7
"Các Mainframe hiện đại (và AIX) là little endian UTF-8 ý thức" UTF-8 không có một endedness ! không có sự xáo trộn các byte xung quanh để đặt các cặp hoặc nhóm bốn vào đúng "trật tự" cho một hệ thống cụ thể! Để phát hiện chuỗi byte UTF-8, có thể hữu ích cần lưu ý rằng byte đầu tiên của chuỗi "byte" chuỗi (byte không phải là "ASCII" đơn giản) có bộ bit MS và tất cả một đến ba liên tiếp các bit ít có ý nghĩa theo sau là bit reset. Tổng số bit được đặt là một byte ít hơn trong mã đó và TẤT CẢ chúng sẽ có bộ MSB ...
SlySven

Câu trả lời:


773

BOM UTF-8 là một chuỗi các byte khi bắt đầu một luồng văn bản ( 0xEF, 0xBB, 0xBF) cho phép người đọc đoán một cách đáng tin cậy hơn một tệp được mã hóa trong UTF-8.

Thông thường, BOM được sử dụng để báo hiệu endianness của một mã hóa, nhưng vì endianness là không thích hợp sang UTF-8, BOM là không cần thiết.

Theo tiêu chuẩn Unicode , BOM cho các tệp UTF-8 không được khuyến nghị :

2.6 Sơ đồ mã hóa

... Việc sử dụng BOM không bắt buộc và cũng không được khuyến nghị cho UTF-8, nhưng có thể gặp phải trong các bối cảnh nơi dữ liệu UTF-8 được chuyển đổi từ các hình thức mã hóa khác sử dụng BOM hoặc sử dụng BOM làm chữ ký UTF-8 . Xem phần phụ của Đơn hàng Byte của Mark Byt trong Phần 16.8, Đặc biệt , để biết thêm thông tin.


114
Có thể không được khuyến nghị nhưng theo kinh nghiệm của tôi về chuyển đổi tiếng Do Thái, BOM đôi khi rất quan trọng đối với nhận dạng UTF-8 trong Excel và có thể tạo ra sự khác biệt giữa Jibrish và tiếng Do Thái
Matanya

26
Nó có thể không được đề xuất nhưng nó đã làm nên điều kỳ diệu đối với kịch bản powershell của tôi khi cố gắng xuất "æøå"
Marius

63
Bất kể tiêu chuẩn nào không được khuyến nghị, điều đó được cho phép và tôi rất thích có một cái gì đó để hoạt động như một chữ ký UTF-8 thay vì giả định hoặc đoán. Phần mềm tương thích Unicode nên / phải có khả năng đối phó với sự hiện diện của nó, vì vậy cá nhân tôi khuyến khích sử dụng phần mềm này.
martineau

30
@ bames53: Có, trong một thế giới lý tưởng lưu trữ mã hóa tệp văn bản dưới dạng siêu dữ liệu hệ thống tệp sẽ là cách tốt hơn để bảo tồn nó. Nhưng hầu hết chúng ta sống trong thế giới thực không thể thay đổi hệ thống tệp của (các) hệ điều hành mà các chương trình của chúng tôi chạy được - vì vậy sử dụng chữ ký BOM độc lập với nền tảng của Unicode có vẻ như là IMHO thay thế tốt nhất và thiết thực nhất.
martineau

34
@martineau Mới hôm qua tôi đã chạy vào một tệp có BOM UTF-8 không phải là UTF-8 (đó là CP936). Điều không may là những người chịu trách nhiệm cho số lượng đau đớn vô cùng lớn do BOM UTF-8 phần lớn không biết đến nó.
bames53

243

Các câu trả lời xuất sắc khác đã trả lời rằng:

  • Không có sự khác biệt chính thức giữa UTF-8 và BOM-ed UTF-8
  • Một chuỗi UTF-8 BOM-ed sẽ bắt đầu với ba byte sau. EF BB BF
  • Các byte đó, nếu có, phải được bỏ qua khi trích xuất chuỗi từ tệp / luồng.

Nhưng, như thông tin bổ sung cho điều này, BOM cho UTF-8 có thể là một cách tốt để "ngửi" nếu một chuỗi được mã hóa trong UTF-8 ... Hoặc nó có thể là một chuỗi hợp pháp trong bất kỳ mã hóa nào khác ...

Ví dụ: dữ liệu [EF BB BF 41 42 43] có thể là:

  • Chuỗi ISO-8859-1 hợp pháp "ï» ABC "
  • Chuỗi UTF-8 hợp pháp "ABC"

Vì vậy, mặc dù có thể rất tuyệt khi nhận ra mã hóa nội dung tệp bằng cách xem các byte đầu tiên, bạn không nên dựa vào điều này, như hiển thị trong ví dụ trên

Mã hóa nên được biết, không được thần thánh.


60
@ Alcott: Bạn hiểu đúng. Chuỗi [EF BB BF 41 42 43] chỉ là một bó byte. Bạn cần thông tin bên ngoài để chọn cách giải thích nó. Nếu bạn tin rằng các byte đó được mã hóa bằng ISO-8859-1, thì chuỗi đó là "ï» ABC ". Nếu bạn tin rằng các byte đó được mã hóa bằng UTF-8, thì đó là "ABC". Nếu bạn không biết, thì bạn phải cố gắng tìm hiểu. BOM có thể là một đầu mối. Sự vắng mặt của ký tự không hợp lệ khi được giải mã là UTF-8 có thể là một thứ khác ... Cuối cùng, trừ khi bạn có thể ghi nhớ / tìm mã hóa bằng cách nào đó, một mảng byte chỉ là một mảng byte.
paercebal

19
@paercebal Mặc dù "ï» ¿"là hợp lệ Latin-1, rất khó có khả năng một tệp văn bản bắt đầu bằng sự kết hợp đó. Điều tương tự giữ cho ucs2-le / là các điểm đánh dấu þ và þÿ. Ngoài ra bạn không bao giờ có thể biết.
dùng877329

16
@deceze Có lẽ không hợp lệ về mặt ngôn ngữ: Đầu tiên ï (không sao), sau đó một số dấu ngoặc kép không có khoảng trắng ở giữa (không ổn). Chỉ ra đó là tiếng Tây Ban Nha nhưng ï không được sử dụng trong tiếng Tây Ban Nha. Kết luận: Nó không phải là Latin-1 với độ chắc chắn cao hơn độ chắc chắn mà không có nó.
dùng877329

20
@user Chắc chắn, nó không nhất thiết phải có ý nghĩa. Nhưng nếu hệ thống của bạn dựa vào việc đoán , đó là nơi không chắc chắn xuất hiện. Một số người dùng độc hại gửi văn bản bắt đầu bằng 3 chữ cái này và hệ thống của bạn đột nhiên cho rằng nó nhìn vào UTF-8 bằng BOM, coi văn bản là UTF-8 cần sử dụng tiếng Latin-1 và một số thao tác tiêm Unicode diễn ra. Chỉ là một ví dụ giả thuyết, nhưng chắc chắn có thể. Bạn không thể đánh giá mã hóa văn bản theo nội dung, thời gian của nó.
lừa dối

40
"Mã hóa nên được biết, không được thần thánh." Trái tim và linh hồn của vấn đề. +1, thưa ngài. Nói cách khác: hoặc chuẩn hóa nội dung của bạn và nói, "Chúng tôi luôn sử dụng mã hóa này. Thời gian. Viết theo cách đó. Đọc theo cách đó" hoặc phát triển một định dạng mở rộng cho phép lưu trữ mã hóa dưới dạng siêu dữ liệu. (Cái sau có lẽ cũng cần một số "mã hóa chuẩn bootstrap". Giống như nói "Phần cho bạn mã hóa luôn là ASCII.")
jpmc26

135

Có ít nhất ba vấn đề với việc đưa BOM vào các tệp được mã hóa UTF-8.

  1. Các tệp không chứa văn bản sẽ không còn trống vì chúng luôn chứa BOM.
  2. Các tệp chứa văn bản nằm trong tập hợp con ASCII của UTF-8 không còn là ASCII nữa vì BOM không phải là ASCII, khiến một số công cụ hiện có bị hỏng và người dùng không thể thay thế các công cụ cũ đó.
  3. Không thể ghép nhiều tệp lại với nhau vì mỗi tệp hiện có BOM ở đầu.

Và, như những người khác đã đề cập, không có đủ và cũng không cần thiết phải có BOM để phát hiện ra rằng thứ gì đó là UTF-8:

  • Điều đó là không đủ vì một chuỗi byte tùy ý có thể xảy ra để bắt đầu với chuỗi chính xác cấu thành BOM.
  • Không cần thiết bởi vì bạn chỉ có thể đọc các byte như thể chúng là UTF-8; nếu thành công, theo định nghĩa, UTF-8 hợp lệ.

8
Điểm 1 "Các tệp không chứa văn bản sẽ không còn trống vì chúng luôn chứa BOM", (1) này kết hợp cấp độ hệ thống tệp của hệ điều hành với cấp độ nội dung được giải thích, cộng với (2) giả định rằng sử dụng BOM người ta phải đặt BOM cũng trong mọi tập tin trống. Giải pháp thực tế cho (1) là không làm (2). Về cơ bản, khiếu nại giảm xuống "có thể chính thức đặt BOM vào một tệp trống khác, do đó ngăn chặn việc phát hiện tệp trống một cách hợp lý nhất (bằng cách kiểm tra kích thước tệp)". Vẫn là phần mềm tốt để có thể đối phó với nó, vì nó có một mục đích.
Chúc mừng và hth. - Alf

7
Điểm 2, "Các tệp chứa văn bản ASCII không còn là ASCII", điều này kết hợp ASCII với UTF-8. Tệp UTF-8 chứa văn bản ASCII không phải là ASCII, đó là UTF-8. Tương tự, tệp UTF-16 chứa văn bản ASCII không phải là ASCII, đó là UTF-16. Và như thế. ASCII là mã byte đơn 7 bit. UTF-8 là phần mở rộng có độ dài biến 8 bit của ASCII. Nếu "công cụ bị hỏng" do> 127 giá trị thì chúng không phù hợp với thế giới 8 bit. Một giải pháp thực tế đơn giản là chỉ sử dụng các tệp ASCII với các công cụ phân tích cho các giá trị byte không phải ASCII. Một giải pháp có lẽ tốt hơn là bỏ những công cụ không tốt đó.
Chúc mừng và hth. - Alf

8
Điểm 3, "Không thể ghép nhiều tệp lại với nhau vì mỗi tệp bây giờ có BOM ở đầu" là sai. Tôi không gặp vấn đề gì khi nối các tệp UTF-8 với BOM, vì vậy rõ ràng là có thể. Tôi nghĩ có lẽ bạn có nghĩa là vùng đất Unix catsẽ không mang lại cho bạn một kết quả rõ ràng , một kết quả chỉ có BOM khi bắt đầu. Nếu bạn có ý đó, thì đó là bởi vì cathoạt động ở cấp độ byte, không phải ở cấp độ nội dung được giải thích và theo cách tương tự catkhông thể đối phó với các bức ảnh, nói. Tuy nhiên, nó không gây hại nhiều. Đó là bởi vì BOM mã hóa một không gian không phá vỡ có chiều rộng bằng không.
Chúc mừng và hth. - Alf

20
@ Cheersandhth.-Alf Câu trả lời này là chính xác. Bạn chỉ đang chỉ ra lỗi của Microsoft.
tchrist

9
@brighty: Mặc dù tình hình không được cải thiện bằng cách thêm một quả bom.
Ded repeatator

84

Dưới đây là những ví dụ về việc sử dụng BOM thực sự gây ra vấn đề thực sự và nhiều người không biết về nó.

BOM phá vỡ các kịch bản

Các tập lệnh Shell, tập lệnh Perl, tập lệnh Python, tập lệnh Ruby, tập lệnh Node.js hoặc bất kỳ tập lệnh thực thi nào khác cần được chạy bởi một trình thông dịch - tất cả đều bắt đầu bằng một dòng shebang trông giống như một trong số đó:

#!/bin/sh
#!/usr/bin/python
#!/usr/local/bin/perl
#!/usr/bin/env node

Nó cho hệ thống biết trình thông dịch nào cần được chạy khi gọi tập lệnh như vậy. Nếu tập lệnh được mã hóa bằng UTF-8, người ta có thể muốn đưa BOM vào đầu. Nhưng thực ra là "#!" nhân vật không chỉ là nhân vật. Thực tế chúng là một con số ma thuật được tạo thành từ hai nhân vật ASCII. Nếu bạn đặt một cái gì đó (như BOM) trước các ký tự đó, thì tệp sẽ trông giống như nó có một số ma thuật khác và điều đó có thể dẫn đến các vấn đề.

Xem Wikipedia, bài viết: Shebang, phần: Số ma thuật :

Các ký tự shebang được biểu thị bằng hai byte giống nhau trong các bảng mã ASCII mở rộng, bao gồm UTF-8, thường được sử dụng cho các tập lệnh và các tệp văn bản khác trên các hệ thống giống như Unix hiện tại. Tuy nhiên, các tệp UTF-8 có thể bắt đầu bằng dấu thứ tự byte tùy chọn (BOM); nếu hàm "exec" đặc biệt phát hiện các byte 0x23 và 0x21, thì sự hiện diện của BOM (0xEF 0xBB 0xBF) trước khi shebang sẽ ngăn trình thông dịch kịch bản lệnh được thực thi.Một số nhà chức trách khuyên không nên sử dụng dấu thứ tự byte trong các tập lệnh POSIX (giống Unix), vì lý do này và vì khả năng tương tác rộng hơn và các mối quan tâm triết học. Ngoài ra, một dấu thứ tự byte là không cần thiết trong UTF-8, vì mã hóa đó không có vấn đề về tuổi thọ; nó chỉ phục vụ để xác định mã hóa là UTF-8. [nhấn mạnh thêm]

BOM là bất hợp pháp trong JSON

Xem RFC 7159, Phần 8.1 :

Việc triển khai KHÔNG PHẢI thêm dấu thứ tự byte vào đầu văn bản JSON.

BOM là dự phòng trong JSON

Không chỉ là bất hợp pháp trong JSON, nó cũng không cần thiết để xác định mã hóa ký tự bởi vì có nhiều cách đáng tin cậy hơn để xác định rõ ràng cả mã hóa ký tự và độ bền được sử dụng trong bất kỳ luồng JSON nào (xem câu trả lời này để biết chi tiết).

BOM phá vỡ trình phân tích cú pháp JSON

Không chỉ bất hợp pháp trong JSON và không cần thiết , nó thực sự phá vỡ tất cả các phần mềm xác định mã hóa bằng phương thức được trình bày trong RFC 4627 :

Xác định mã hóa và độ bền của JSON, kiểm tra bốn byte đầu tiên cho byte NUL:

00 00 00 xx - UTF-32BE
00 xx 00 xx - UTF-16BE
xx 00 00 00 - UTF-32LE
xx 00 xx 00 - UTF-16LE
xx xx xx xx - UTF-8

Bây giờ, nếu tệp bắt đầu bằng BOM, nó sẽ trông như thế này:

00 00 FE FF - UTF-32BE
FE FF 00 xx - UTF-16BE
FF FE 00 00 - UTF-32LE
FF FE xx 00 - UTF-16LE
EF BB BF xx - UTF-8

Lưu ý rằng:

  1. UTF-32BE không bắt đầu bằng ba NUL, vì vậy nó sẽ không được công nhận
  2. UTF-32LE byte đầu tiên không được theo sau bởi ba NUL, vì vậy nó sẽ không được công nhận
  3. UTF-16BE chỉ có một NUL trong bốn byte đầu tiên, vì vậy nó sẽ không được công nhận
  4. UTF-16LE chỉ có một NUL trong bốn byte đầu tiên, vì vậy nó sẽ không được công nhận

Tùy thuộc vào việc triển khai, tất cả những thứ đó có thể được hiểu không chính xác là UTF-8 và sau đó bị hiểu sai hoặc bị từ chối là UTF-8 không hợp lệ hoặc hoàn toàn không được công nhận.

Ngoài ra, nếu việc triển khai kiểm tra JSON hợp lệ như tôi khuyến nghị, nó sẽ từ chối ngay cả đầu vào thực sự được mã hóa dưới dạng UTF-8, bởi vì nó không bắt đầu bằng ký tự ASCII <128 như RFC.

Các định dạng dữ liệu khác

BOM trong JSON là không cần thiết, là bất hợp pháp và phá vỡ phần mềm hoạt động chính xác theo RFC. Nên là không có giới hạn khi không sử dụng nó sau đó, luôn có những người khăng khăng phá vỡ JSON bằng cách sử dụng BOM, nhận xét, quy tắc trích dẫn khác nhau hoặc các loại dữ liệu khác nhau. Tất nhiên bất cứ ai cũng có thể tự do sử dụng những thứ như BOM hoặc bất cứ thứ gì khác nếu bạn cần - chỉ cần đừng gọi nó là JSON.

Đối với các định dạng dữ liệu khác ngoài JSON, hãy xem nó thực sự trông như thế nào. Nếu mã hóa duy nhất là UTF- * và ký tự đầu tiên phải là ký tự ASCII thấp hơn 128 thì bạn đã có tất cả thông tin cần thiết để xác định cả mã hóa và độ bền của dữ liệu của bạn. Thêm các BOM ngay cả khi là một tính năng tùy chọn sẽ chỉ khiến nó phức tạp hơn và dễ bị lỗi hơn.

Các ứng dụng khác của BOM

Đối với việc sử dụng bên ngoài JSON hoặc script, tôi nghĩ rằng đã có câu trả lời rất tốt ở đây. Tôi muốn thêm thông tin chi tiết cụ thể về kịch bản và tuần tự hóa, bởi vì đó là một ví dụ về các ký tự BOM gây ra vấn đề thực sự.


5
rfc7159 thay thế rfc4627 thực sự gợi ý hỗ trợ BOM có thể không quá tệ. Về cơ bản việc không có BOM chỉ là một loại bùn mơ hồ để phần mềm Windows và Unix cũ không nhận biết Unicode vẫn có thể xử lý utf-8.
Eric Grange

2
Âm thanh như JSON cần cập nhật để hỗ trợ nó, tương tự với các tập lệnh Perl, tập lệnh Python, tập lệnh Ruby, Node.js. Chỉ vì các nền tảng này được chọn không bao gồm hỗ trợ, không nhất thiết phải hủy sử dụng cho BOM. Apple đã cố gắng giết Adobe trong một vài năm nay và Adobe vẫn còn tồn tại. Nhưng một bài khai sáng.
htm11h

13
@EricGrange, bạn dường như rất ủng hộ BOM, nhưng không nhận ra rằng điều này sẽ khiến định dạng "văn bản đơn giản" tối ưu , phổ biến, tối ưu , phổ biến trở thành một di tích của UTF8 trước đây! Theo định nghĩa, việc thêm bất kỳ loại tiêu đề (trong băng) nào vào luồng văn bản đơn giản sẽ áp đặt một giao thức bắt buộc cho các tệp văn bản đơn giản nhất, làm cho nó không bao giờ trở thành "đơn giản nhất"! Và vì cái gì đạt được? Để hỗ trợ tất cả các khác , mã hóa CP xưa mà cũng không có chữ ký, vì vậy bạn có thể nhầm lẫn chúng với UTF-8? (BTW, ASCII cũng là UTF-8. Vì vậy, BOM cho những người đó cũng vậy ?;) Thôi nào.)
Sz.

2
Câu trả lời này là lý do tại sao tôi đi đến câu hỏi này! Tôi tạo các tập lệnh bash của mình trong Windows và gặp rất nhiều vấn đề khi xuất bản các tập lệnh đó lên Linux! Điều tương tự với các tập tin jason.
Tono Nam

2
Tôi ước tôi có thể bỏ phiếu cho câu trả lời này khoảng năm mươi lần. Tôi cũng muốn nói thêm rằng tại thời điểm này, UTF-8 đã chiến thắng trong cuộc chiến tiêu chuẩn và gần như tất cả các văn bản được sản xuất trên Internet là UTF-8. Một số ngôn ngữ lập trình phổ biến nhất (như C # và Java) sử dụng UTF-16 trong nội bộ, nhưng khi các lập trình viên sử dụng các ngôn ngữ đó ghi tệp vào luồng đầu ra, họ hầu như luôn mã hóa chúng dưới dạng UTF-8. Do đó, không còn ý nghĩa khi có BOM để đánh dấu tệp UTF-8; UTF-8 phải là mặc định bạn sử dụng khi đọc và chỉ thử các mã hóa khác nếu giải mã UTF-8 không thành công.
rmunn

51

Có gì khác nhau giữa UTF-8 và UTF-8 không có BOM?

Câu trả lời ngắn: Trong UTF-8, BOM được mã hóa dưới dạng byte EF BB BFở đầu tệp.

Câu trả lời dài:

Ban đầu, người ta hy vọng rằng Unicode sẽ được mã hóa theo UTF-16 / UCS-2. BOM được thiết kế cho hình thức mã hóa này. Khi bạn có các đơn vị mã 2 byte, cần phải chỉ ra hai byte đó theo thứ tự nào và một quy ước chung để thực hiện điều này là bao gồm ký tự U + FEFF làm "Dấu thứ tự byte" ở đầu dữ liệu. Ký tự U + FFFE không được gán vĩnh viễn để có thể sử dụng sự hiện diện của nó để phát hiện thứ tự byte sai.

UTF-8 có cùng thứ tự byte bất kể tuổi thọ của nền tảng, do đó, không cần một dấu thứ tự byte. Tuy nhiên, nó có thể xảy ra (dưới dạng chuỗi byte EF BB FF) trong dữ liệu đã được chuyển đổi thành UTF-8 từ UTF-16 hoặc dưới dạng "chữ ký" để chỉ ra rằng dữ liệu là UTF-8.

Cái nào tốt hơn?

Không có. Như Martin Côte đã trả lời, tiêu chuẩn Unicode không khuyến nghị điều đó. Nó gây ra vấn đề với phần mềm không nhận biết BOM.

Cách tốt hơn để phát hiện xem một tệp có phải là UTF-8 hay không là thực hiện kiểm tra tính hợp lệ. UTF-8 có các quy tắc nghiêm ngặt về chuỗi byte nào là hợp lệ, do đó xác suất dương tính giả là không đáng kể. Nếu một chuỗi byte trông giống như UTF-8, thì có lẽ là như vậy.


8
điều này cũng sẽ làm mất hiệu lực UTF-8 hợp lệ với một byte sai lầm duy nhất trong đó, mặc dù: /
endolith

8
-1 lại "Nó gây ra sự cố với phần mềm không nhận biết BOM.", Điều đó chưa bao giờ là vấn đề đối với tôi, nhưng ngược lại, sự vắng mặt của BOM gây ra sự cố với phần mềm nhận biết BOM (cụ thể là Visual C ++) đã là một vấn đề vấn đề. Vì vậy, tuyên bố này rất cụ thể về nền tảng , một quan điểm đất hẹp của Unix, nhưng được trình bày sai lệch như thể nó được áp dụng nói chung. Mà nó không có.
Chúc mừng và hth. - Alf

6
Không, UTF-8 không có BOM. Câu trả lời này không chính xác. Xem Tiêu chuẩn Unicode.
tchrist

2
Bạn thậm chí có thể nghĩ rằng bạn có một tệp ASCII thuần khi chỉ nhìn vào các byte. Nhưng đây có thể là một tệp utf-16 cũng là nơi bạn phải xem các từ chứ không phải các byte. Phần mềm hiện đại nên được biết về BOM. Vẫn đọc utf-8 có thể thất bại nếu phát hiện các chuỗi không hợp lệ, các loại tiền mã hóa có thể sử dụng một chuỗi nhỏ hơn hoặc các loại tiền mã hóa thay thế. Đối với việc đọc utf-16 cũng có thể thất bại khi có những người thay thế mồ côi.
sáng

1
@Alf, tôi không đồng ý với cách giải thích của bạn về thái độ không phải BOM là " đặc thù nền tảng , quan điểm đất hẹp của Unix". Đối với tôi, cách duy nhất mà sự hẹp hòi có thể nằm ở "vùng đất Unix" là nếu MS và Visual C ++ xuất hiện trước * NIX, điều mà họ không làm được. Thực tế là MS (tôi giả cố ý) bắt đầu sử dụng một BOM trong UTF-8 chứ không phải là UTF-16 gợi ý với tôi rằng họ thăng chức vi phạm sh, perl, g++, và nhiều công cụ miễn phí và mạnh mẽ khác. Bạn muốn mọi thứ để làm việc? Chỉ cần mua các phiên bản MS. MS đã tạo ra vấn đề dành riêng cho nền tảng, giống như thảm họa trong phạm vi \ x80- \ x95 của họ.
bballdave025

30

UTF-8 với BOM được xác định tốt hơn. Tôi đã đi đến kết luận này một cách khó khăn. Tôi đang làm việc trên một dự án trong đó một trong các kết quả là tệp CSV , bao gồm các ký tự Unicode.

Nếu tệp CSV được lưu mà không có BOM, Excel sẽ nghĩ đó là ANSI và hiển thị vô nghĩa. Khi bạn thêm "EF BB BF" ở phía trước (ví dụ: bằng cách lưu lại bằng Notepad với UTF-8; hoặc Notepad ++ với UTF-8 với BOM), Excel sẽ mở nó tốt.

Việc chuẩn bị ký tự BOM cho các tệp văn bản Unicode được RFC 3629 khuyến nghị: "UTF-8, định dạng chuyển đổi của ISO 10646", tháng 11 năm 2003 tại http://tools.ietf.org/html/rfc3629 (thông tin cuối cùng này được tìm thấy tại: http://www.herongyang.com/Unicode/Notepad-Byte-Order-Mark-BOM-FEFF-EFBBBF.html )


6
Cảm ơn về mẹo tuyệt vời này trong trường hợp một người đang tạo tệp UTF-8 để Excel sử dụng. Trong những trường hợp khác, tôi vẫn sẽ làm theo các câu trả lời khác và bỏ qua BOM.
barfuin

5
Nó cũng hữu ích nếu bạn tạo các tệp chỉ chứa ASCII và sau đó có thể không được thêm vào nó. Tôi vừa gặp phải một vấn đề như vậy: phần mềm mong đợi utf8, tạo tệp với một số dữ liệu để người dùng chỉnh sửa. Nếu tệp ban đầu chỉ chứa ASCII, được mở trong một số trình soạn thảo và sau đó được lưu, nó sẽ kết thúc bằng tiếng Latin-1 và mọi thứ đều bị hỏng. Nếu tôi thêm BOM, trình soạn thảo sẽ được phát hiện là UTF8 và mọi thứ đều hoạt động.
Roberto Alsina

1
Tôi đã tìm thấy nhiều công cụ liên quan đến lập trình yêu cầu BOM nhận dạng đúng các tệp UTF-8. Visual Studio, SSMS, SoureTree ....
kjbartel

5
Nơi nào bạn đọc khuyến nghị sử dụng BOM vào RFC đó? Hầu hết, có một khuyến nghị mạnh mẽ là không cấm nó trong những trường hợp nhất định mà việc đó là khó khăn.
Ded repeatator

8
Excel nghĩ rằng đó là ANSI và hiển thị vô nghĩa thì vấn đề là ở Excel.
Isaac

17

BOM có xu hướng bùng nổ (không có ý định chơi chữ (sic)) ở đâu đó, một nơi nào đó. Và khi nó bùng nổ (ví dụ: không được trình duyệt, trình chỉnh sửa, v.v.) nhận ra, nó sẽ hiển thị dưới dạng các ký tự lạ ở đầu tài liệu (ví dụ: tệp HTML, phản hồi JSON , RSS , v.v.) và gây ra sự bối rối như vấn đề mã hóa gần đây gặp phải trong cuộc nói chuyện của Obama trên Twitter .

Thật khó chịu khi nó xuất hiện ở những nơi khó gỡ lỗi hoặc khi thử nghiệm bị bỏ qua. Vì vậy, tốt nhất là tránh nó trừ khi bạn phải sử dụng nó.


Có, chỉ mất hàng giờ để xác định sự cố do tệp được mã hóa thành UTF-8 thay vì UTF-8 mà không có BOM. (Vấn đề chỉ xuất hiện trong IE7 do đó đã dẫn tôi đến một cuộc rượt đuổi khá ngông. Tôi đã sử dụng "bao gồm" của Django.)
user984003

Độc giả tương lai: Lưu ý rằng vấn đề tweet mà tôi đã đề cập ở trên không liên quan chặt chẽ đến BOM, nhưng nếu có, thì tweet sẽ bị cắt xén theo cách tương tự, nhưng khi bắt đầu tweet.
Halil Özgür

12
@ user984003 Không, vấn đề là Microsoft đã đánh lừa bạn. Cái mà nó gọi là UTF-8 không phải là UTF-8. Cái mà nó gọi là UTF-8 mà không có BOM là UTF-8 thực sự là gì.
tchrist

"sic" thêm gì vào "không có ý định chơi chữ" của bạn
JoelFan

2
@JoelFan Tôi không thể nhớ lại nữa nhưng tôi đoán rằng trò chơi chữ có thể đã được dự định mặc dù yêu cầu của tác giả :)
Halil zgür

17

Câu hỏi: Có gì khác nhau giữa UTF-8 và UTF-8 mà không có BOM? Cái nào tốt hơn?

Dưới đây là một số trích đoạn từ bài viết Wikipedia về dấu thứ tự byte (BOM) mà tôi tin rằng cung cấp một câu trả lời chắc chắn cho câu hỏi này.

Về ý nghĩa của BOM và UTF-8:

Tiêu chuẩn Unicode cho phép BOM trong UTF-8 , nhưng không yêu cầu hoặc không khuyến nghị sử dụng. Thứ tự byte không có ý nghĩa trong UTF-8, do đó, việc sử dụng duy nhất trong UTF-8 là để báo hiệu khi bắt đầu luồng văn bản được mã hóa trong UTF-8.

Đối số KHÔNG sử dụng BOM:

Động lực chính cho việc không sử dụng BOM là khả năng tương thích ngược với phần mềm không nhận biết Unicode ... Một động lực khác để không sử dụng BOM là khuyến khích UTF-8 làm mã hóa "mặc định".

Lập luận CHO sử dụng một BOM:

Đối số cho việc sử dụng BOM là không có nó, cần phải phân tích heuristic để xác định ký tự nào mã hóa một tệp đang sử dụng. Trong lịch sử phân tích như vậy, để phân biệt các mã hóa 8 bit khác nhau, rất phức tạp, dễ bị lỗi và đôi khi chậm. Một số thư viện có sẵn để giảm bớt tác vụ, chẳng hạn như Trình phát hiện bộ ký tự phổ quát Mozilla và Các thành phần quốc tế cho Unicode.

Các lập trình viên lầm tưởng rằng việc phát hiện UTF-8 cũng khó khăn không kém (không phải vì phần lớn các chuỗi byte là UTF-8 không hợp lệ, trong khi các mã hóa mà các thư viện này đang cố gắng phân biệt cho phép tất cả các chuỗi byte có thể). Do đó, không phải tất cả các chương trình nhận biết Unicode đều thực hiện phân tích như vậy và thay vào đó dựa vào BOM.

Cụ thể, trình biên dịch và trình thông dịch của Microsoft và nhiều phần mềm trên Microsoft Windows như Notepad sẽ không đọc chính xác văn bản UTF-8 trừ khi nó chỉ có các ký tự ASCII hoặc bắt đầu bằng BOM và sẽ thêm BOM vào đầu khi lưu văn bản dưới dạng UTF-8. Google Docs sẽ thêm BOM khi tài liệu Microsoft Word được tải xuống dưới dạng tệp văn bản thuần túy.

Trên đó là tốt hơn, VỚI hoặc KHÔNG CÓ BOM:

Các IETF khuyến cáo rằng nếu một giao thức (a) luôn luôn sử dụng UTF-8, hoặc (b) có một số cách khác để chỉ những gì mã hóa đang được sử dụng, sau đó nó “NÊN cấm sử dụng U + FEFF như một chữ ký.”

Kết luận của tôi:

Sử dụng BOM chỉ nếu khả năng tương thích với một ứng dụng phần mềm là hoàn toàn cần thiết.

Cũng lưu ý rằng mặc dù bài viết Wikipedia được tham chiếu chỉ ra rằng nhiều ứng dụng của Microsoft dựa vào BOM để phát hiện chính xác UTF-8, nhưng đây không phải là trường hợp của tất cả các ứng dụng của Microsoft. Ví dụ, như ra nhọn bởi @barlop , khi sử dụng Command Windows Prompt với UTF-8 , lệnh như vậy typemoretôi không mong đợi các BOM có mặt. Nếu BOM mặt, nó có thể có vấn đề như đối với các ứng dụng khác.


† Các chcplệnh Mời hỗ trợ cho UTF-8 ( mà không cần sự BOM) thông qua mã trang 65001 .


5
Tôi nên nghiêm khắc hơn để KHÔNG CÓ BOM . Tôi thấy rằng .htaccessgzip compressionkết hợp với BOM UTF-8 gây ra lỗi mã hóa Thay đổi thành Mã hóa trong UTF-8 mà không có BOM làm theo đề xuất như được giải thích ở đây giải quyết các vấn đề
Chetabahana

1
'Một động lực khác để không sử dụng BOM là khuyến khích UTF-8 làm mã hóa "mặc định". - Đó là một đối số mạnh mẽ và hợp lệ, đến mức bạn thực sự có thể dừng câu trả lời ở đó! ...;-Trừ khi bạn có một ý tưởng tốt hơn cho biểu diễn văn bản phổ quát, đó là. ) mớ hỗn độn của tất cả các mã hóa byte đơn không có siêu dữ liệu cổ đại, thay vì có "cái" là niềm vui thuần túy.)
Sz.

Xem thêm nhận xét này về cách thêm BOM (hoặc bất cứ thứ gì!) Vào đơn giản nhất trong các định dạng tệp văn bản, "văn bản thuần túy", có nghĩa là ngăn chính xác định dạng mã hóa văn bản phổ quát tốt nhất khỏi "đơn giản" và "đơn giản" (nghĩa là "không cần thiết")! ...
Sz.

BOM chủ yếu là có vấn đề trên Linux vì nhiều tiện ích không thực sự hỗ trợ Unicode để bắt đầu (ví dụ, chúng sẽ vui vẻ cắt ngắn ở giữa các điểm mã). Đối với hầu hết các môi trường phần mềm hiện đại khác, hãy sử dụng BOM bất cứ khi nào mã hóa không rõ ràng (thông qua thông số kỹ thuật hoặc siêu dữ liệu).
Eric Grange

9

Câu hỏi này đã có một câu trả lời một triệu và nhiều câu trả lời khá hay, nhưng tôi muốn thử và làm rõ khi nào BOM nên hay không nên sử dụng.

Như đã đề cập, bất kỳ việc sử dụng BOM UTF (Dấu thứ tự Byte) trong việc xác định xem một chuỗi có phải là UTF-8 hay không là phỏng đoán có giáo dục. Nếu có sẵn siêu dữ liệu thích hợp (như charset="utf-8"), thì bạn đã biết những gì bạn sẽ sử dụng, nhưng nếu không, bạn sẽ cần phải kiểm tra và đưa ra một số giả định. Điều này liên quan đến việc kiểm tra xem tệp có xuất phát từ chuỗi bắt đầu bằng mã byte thập lục phân hay không, EF BB BF.

Nếu tìm thấy mã byte tương ứng với BOM UTF-8, xác suất đủ cao để giả sử đó là UTF-8 và bạn có thể đi từ đó. Tuy nhiên, khi buộc phải đưa ra dự đoán này, kiểm tra lỗi bổ sung trong khi đọc vẫn sẽ là một ý tưởng tốt trong trường hợp có thứ gì đó bị cắt xén. Bạn chỉ nên giả sử BOM không phải là UTF-8 (tức là latin-1 hoặc ANSI) nếu đầu vào chắc chắn không nên là UTF-8 dựa trên nguồn của nó. Tuy nhiên, nếu không có BOM, bạn chỉ cần xác định liệu nó có phải là UTF-8 hay không bằng cách xác nhận mã hóa.

Tại sao BOM không được khuyến nghị?

  1. Phần mềm không nhận biết hoặc không tuân thủ Unicode có thể cho rằng đó là Latin-1 hoặc ANSI và sẽ không loại bỏ BOM khỏi chuỗi, điều này rõ ràng có thể gây ra sự cố.
  2. Nó không thực sự cần thiết (chỉ cần kiểm tra xem nội dung có tuân thủ hay không và luôn sử dụng UTF-8 làm dự phòng khi không tìm thấy mã hóa tuân thủ)

Khi nào bạn nên mã hóa bằng BOM?

Nếu bạn không thể ghi siêu dữ liệu theo bất kỳ cách nào khác (thông qua thẻ ký tự hoặc meta hệ thống tệp) và các chương trình đang được sử dụng như BOM, bạn nên mã hóa bằng BOM. Điều này đặc biệt đúng trên Windows khi mọi thứ không có BOM thường được cho là đang sử dụng trang mã kế thừa. BOM nói với các chương trình như Office rằng, vâng, văn bản trong tệp này là Unicode; đây là mã hóa được sử dụng.

Khi nói đến nó, các tệp duy nhất tôi thực sự gặp vấn đề là CSV. Tùy thuộc vào chương trình, nó phải hoặc không phải có BOM. Ví dụ: nếu bạn đang sử dụng Excel 2007+ trên Windows, nó phải được mã hóa bằng BOM nếu bạn muốn mở nó một cách trơn tru và không phải dùng đến việc nhập dữ liệu.


2
Phần cuối cùng trong câu trả lời của bạn là chính xác 100%: lý do duy nhất để sử dụng BOM là khi bạn phải tương tác với phần mềm lỗi không sử dụng UTF-8 làm mặc định để phân tích các tệp không xác định.
rmunn

8

Cần lưu ý rằng đối với một số tệp, bạn không được có BOM ngay cả trên Windows. Ví dụ là SQL*plushoặc VBScripttập tin. Trong trường hợp các tệp như vậy chứa BOM, bạn sẽ gặp lỗi khi bạn cố thực thi chúng.


8

UTF-8 với BOM chỉ giúp nếu tệp thực sự chứa một số ký tự không phải ASCII. Nếu nó được bao gồm và không có bất kỳ thứ gì, thì nó có thể sẽ phá vỡ các ứng dụng cũ hơn có thể giải thích tệp là ASCII đơn giản. Các ứng dụng này chắc chắn sẽ thất bại khi chúng gặp một ký tự không phải ASCII, vì vậy theo tôi, BOM chỉ nên được thêm vào khi tệp có thể, và không nên được hiểu là ASCII đơn giản.

Tôi muốn làm rõ rằng tôi không muốn có BOM nào cả. Thêm nó vào nếu một số rác cũ bị hỏng mà không có nó, và thay thế ứng dụng cũ đó là không khả thi.

Đừng làm bất cứ điều gì mong đợi BOM cho UTF-8.


7

Được trích dẫn ở cuối trang Wikipedia trên BOM: http://en.wikipedia.org/wiki/Byte-order_mark#cite_note-2

"Việc sử dụng BOM không bắt buộc và cũng không được khuyến nghị cho UTF-8, nhưng có thể gặp phải trong các bối cảnh nơi dữ liệu UTF-8 được chuyển đổi từ các hình thức mã hóa khác sử dụng BOM hoặc trong đó BOM được sử dụng làm chữ ký UTF-8"


2
Bạn có ví dụ nào về việc phần mềm đưa ra quyết định có nên sử dụng UTF-8 có / không có BOM hay không, dựa trên việc mã hóa trước đó có được mã hóa từ đó, có BOM hay không?! Đó dường như là một yêu sách vô lý
barlop

7

UTF-8 không có BOM không có BOM, điều này không làm cho nó tốt hơn UTF-8 với BOM, ngoại trừ khi người tiêu dùng tệp cần biết (hoặc sẽ có lợi khi biết) liệu tệp có được mã hóa UTF-8 không hay không.

BOM thường hữu ích để xác định độ bền của mã hóa, không cần thiết cho hầu hết các trường hợp sử dụng.

Ngoài ra, BOM có thể là tiếng ồn / nỗi đau không cần thiết cho những người tiêu dùng không biết hoặc không quan tâm đến nó và có thể dẫn đến sự nhầm lẫn của người dùng.


2
"không sử dụng UTF-8 vì dù sao nó cũng là 8 bit cho mỗi glyph." À không, chỉ có glyphs ASCII-7 là 8 bit trong UTF-8. Bất cứ điều gì ngoài đó sẽ là 16, 24 hoặc 32 bit.
Powerlord

3
"BOM thường hữu ích để xác định độ bền của mã hóa, không cần thiết cho hầu hết các trường hợp sử dụng." ... endianness đơn giản không áp dụng cho UTF-8, bất kể trường hợp sử dụng
JoelFan

6

Tôi nhìn điều này từ một quan điểm khác. Tôi nghĩ UTF-8 với BOM tốt hơn vì nó cung cấp thêm thông tin về tệp. Tôi chỉ sử dụng UTF-8 mà không có BOM nếu tôi gặp vấn đề.

Tôi đang sử dụng nhiều ngôn ngữ (thậm chí Cyrillic ) trên các trang của mình trong một thời gian dài và khi các tệp được lưu mà không có BOM và tôi mở lại chúng để chỉnh sửa bằng trình chỉnh sửa (như cherouvim cũng lưu ý), một số ký tự bị hỏng.

Lưu ý rằng Notepad cổ điển của Windows sẽ tự động lưu tệp bằng BOM khi bạn cố lưu tệp mới được tạo bằng mã hóa UTF-8.

Cá nhân tôi lưu các tệp kịch bản phía máy chủ (.asp, .ini, .aspx) bằng các tệp BOM.html mà không có BOM .


4
Cảm ơn các mẹo tuyệt vời về Windows cổ điển Notepad. Tôi đã dành thời gian để tìm hiểu chính xác điều tương tự. Hậu quả của tôi là luôn sử dụng Notepad ++ thay vì Windows cổ điển. :-)
barfuin

Bạn nên sử dụng madedit. Đây là Trình chỉnh sửa duy nhất - ở chế độ hex - hiển thị một ký tự nếu bạn chọn chuỗi byte utf-8 thay vì Cơ sở 1: 1 giữa byte và ký tự. Trình soạn thảo hex nhận biết về tệp UTF-8 sẽ hoạt động giống như madedit!
sáng 9/2/2015

@brighty Tôi không nghĩ bạn cần một đối một vì lợi ích của BOM. không thành vấn đề, sẽ không mất nhiều thời gian để nhận ra BOM utf-8 là efbbbf hoặc fffe (của fffe nếu đọc sai). Người ta có thể chỉ cần xóa các byte đó. Mặc dù nó không phải là một ánh xạ cho phần còn lại của tệp, nhưng cũng có thể xóa từng byte theo từng byte
barlop

@barlop Tại sao bạn muốn xóa BOM utf-8 nếu nội dung của tệp được mã hóa utf-8? BOM được công nhận bởi Trình xem văn bản hiện đại, Điều khiển văn bản cũng như Trình chỉnh sửa văn bản. Một khung nhìn một đến một của chuỗi utf-8 không có ý nghĩa gì, vì n byte dẫn đến một ký tự. Tất nhiên, một trình soạn thảo văn bản hoặc trình soạn thảo hex sẽ cho phép xóa bất kỳ byte nào, nhưng điều này có thể dẫn đến các chuỗi utf-8 không hợp lệ.
sáng

@brighty utf-8 với bom là mã hóa và utf-8 không có bom là mã hóa. Dấu nhắc cmd sử dụng utf8 không có bom .. vì vậy nếu bạn có tệp utf8, bạn chạy lệnh chcp 65001để hỗ trợ utf8, đó là utf8 không có bom. Nếu bạn làm điều type myfileđó sẽ chỉ hiển thị đúng nếu không có bom. Nếu bạn làm echo aaa>a.ahoặc echo אאא>a.a xuất ký tự ra tệp aa và bạn có chcp 65001, nó sẽ xuất ra mà không có BOM.
barlop

6

Khi bạn muốn hiển thị thông tin được mã hóa trong UTF-8, bạn có thể không gặp phải vấn đề gì. Khai báo ví dụ một tài liệu HTML là UTF-8 và bạn sẽ có mọi thứ được hiển thị trong trình duyệt của bạn được chứa trong phần thân của tài liệu.

Nhưng đây không phải là trường hợp khi chúng ta có tệp văn bản, CSV và XML, trên Windows hoặc Linux.

Ví dụ: một tệp văn bản trong Windows hoặc Linux, một trong những thứ dễ nhất có thể tưởng tượng, nó không phải (thường là) UTF-8.

Lưu nó dưới dạng XML và khai báo nó dưới dạng UTF-8:

<?xml version="1.0" encoding="UTF-8"?>

Nó sẽ không hiển thị (nó sẽ không được đọc) một cách chính xác, ngay cả khi nó được khai báo là UTF-8.

Tôi đã có một chuỗi dữ liệu chứa các chữ cái tiếng Pháp, cần được lưu dưới dạng XML để cung cấp. Không tạo tệp UTF-8 ngay từ đầu (thay đổi tùy chọn trong IDE và "Tạo tệp mới") hoặc thêm BOM ở đầu tệp

$file="\xEF\xBB\xBF".$string;

Tôi đã không thể lưu các chữ cái tiếng Pháp trong một tệp XML.


1
FTM, trong XML, tôi nghĩ bạn nên giữ tệp dưới dạng ASCII và sử dụng các thực thể thay thế.
Alois Mahdal

4
Tôi biết đây là một câu trả lời cũ, nhưng tôi chỉ muốn đề cập rằng nó sai. Các tệp văn bản trên Linux (không thể nói cho các Unix khác) thường / là / UTF-8.
Funcino

6

Một sự khác biệt thực tế là nếu bạn viết một tập lệnh shell cho Mac OS X và lưu nó dưới dạng UTF-8 đơn giản, bạn sẽ nhận được phản hồi:

#!/bin/bash: No such file or directory

để đáp ứng với dòng shebang chỉ định shell nào bạn muốn sử dụng:

#!/bin/bash

Nếu bạn lưu dưới dạng UTF-8, không có BOM (nói trong BBEdit ) tất cả sẽ ổn.


8
Đó là bởi vì Microsoft đã hoán đổi ý nghĩa của những gì tiêu chuẩn nói. UTF-8 không có BOM: họ đã tạo Microsoft UTF-8 để chèn BOM giả trước luồng dữ liệu và sau đó nói với bạn rằng không, đây thực sự là UTF-8. Không phải vậy. Nó chỉ là mở rộng và hỏng.
tchrist

4

Như đã đề cập ở trên, UTF-8 với BOM có thể gây ra sự cố với phần mềm không nhận biết BOM (hoặc tương thích). Tôi đã từng chỉnh sửa các tệp HTML được mã hóa dưới dạng UTF-8 + BOM với KompoZer dựa trên Mozilla , vì khách hàng yêu cầu chương trình WYSIWYG .

Luôn luôn bố trí sẽ bị phá hủy khi tiết kiệm. Tôi phải mất một thời gian để tìm hiểu về cách này. Các tệp này sau đó hoạt động tốt trong Firefox, nhưng lại cho thấy một sự giải quyết CSS trong Internet Explorer phá hủy bố cục. Sau khi loay hoay với các tệp CSS được liên kết trong nhiều giờ mà không có kết quả, tôi phát hiện ra rằng Internet Explorer không thích tệp HTML BOMfed. Không bao giờ lặp lại.

Ngoài ra, tôi chỉ tìm thấy điều này trong Wikipedia:

Các ký tự shebang được biểu thị bằng hai byte giống nhau trong các bảng mã ASCII mở rộng, bao gồm UTF-8, thường được sử dụng cho các tập lệnh và các tệp văn bản khác trên các hệ thống giống như Unix hiện tại. Tuy nhiên, các tệp UTF-8 có thể bắt đầu bằng dấu thứ tự byte tùy chọn (BOM); nếu hàm "exec" đặc biệt phát hiện các byte 0x23 0x21, thì sự hiện diện của BOM (0xEF 0xBB 0xBF) trước khi shebang sẽ ngăn trình thông dịch kịch bản lệnh được thực thi. Một số nhà chức trách khuyên không nên sử dụng dấu thứ tự byte trong các tập lệnh POSIX (giống như Unix), vì lý do này và vì khả năng tương tác rộng hơn và mối quan tâm triết học


4

Câu hỏi thường gặp về Dấu hiệu đặt hàng Unicode (BOM) cung cấp câu trả lời ngắn gọn:

Q: Làm thế nào tôi nên đối phó với BOM?

A: Dưới đây là một số hướng dẫn để làm theo:

  1. Một giao thức cụ thể (ví dụ: các quy ước của Microsoft cho các tệp .txt) có thể yêu cầu sử dụng BOM trên các luồng dữ liệu Unicode nhất định, chẳng hạn như các tệp. Khi bạn cần tuân thủ một giao thức như vậy, hãy sử dụng BOM.

  2. Một số giao thức cho phép các BOM tùy chọn trong trường hợp văn bản không được mã hóa. Trong những trường hợp đó,

    • Trong đó một luồng dữ liệu văn bản được biết là văn bản thuần túy, nhưng mã hóa không xác định, BOM có thể được sử dụng làm chữ ký. Nếu không có BOM, mã hóa có thể là bất cứ thứ gì.

    • Trong đó một luồng dữ liệu văn bản được biết là văn bản Unicode đơn giản (nhưng không phải là endian), thì BOM có thể được sử dụng làm chữ ký. Nếu không có BOM, văn bản nên được hiểu là big endian.

  3. Một số giao thức hướng byte mong đợi các ký tự ASCII ở đầu tệp. Nếu UTF-8 được sử dụng với các giao thức này, nên sử dụng BOM làm chữ ký biểu mẫu mã hóa.

  4. Trong đó loại chính xác của luồng dữ liệu được biết đến (ví dụ: Unicode big endian hoặc Unicode little endian), không nên sử dụng BOM. Đặc biệt, bất cứ khi nào một luồng dữ liệu được khai báo là UTF-16BE, UTF-16LE, UTF-32BE hoặc UTF-32LE thì không được sử dụng BOM.


1

Từ http://en.wikipedia.org/wiki/Byte-order_mark :

Dấu thứ tự byte (BOM) là một ký tự Unicode được sử dụng để báo hiệu độ bền (thứ tự byte) của tệp văn bản hoặc luồng. Điểm mã của nó là U + FEFF. Việc sử dụng BOM là tùy chọn và, nếu được sử dụng, sẽ xuất hiện ở đầu luồng văn bản. Ngoài việc sử dụng cụ thể của nó như là một chỉ báo theo thứ tự byte, ký tự BOM cũng có thể chỉ ra biểu thức Unicode nào trong số các biểu diễn Unicode mà văn bản được mã hóa.

Luôn sử dụng BOM trong tệp của bạn sẽ đảm bảo rằng nó luôn mở chính xác trong trình chỉnh sửa hỗ trợ UTF-8 và BOM.

Vấn đề thực sự của tôi với sự vắng mặt của BOM là như sau. Giả sử chúng ta có một tệp chứa:

abc

Không có BOM, điều này sẽ mở ra như ANSI trong hầu hết các trình soạn thảo. Vì vậy, một người dùng khác của tệp này mở nó và thêm một số ký tự gốc, ví dụ:

abg-αβγ

Rất tiếc ... Bây giờ tệp vẫn ở ANSI và đoán xem, "αβγ" không chiếm 6 byte, nhưng 3. Đây không phải là UTF-8 và điều này gây ra các vấn đề khác sau này trong chuỗi phát triển.


9
Đảm bảo rằng các byte giả xuất hiện ở phần đầu của phần mềm không nhận biết BOM. Yay
Romain

1
@Romain Muller: ví dụ: PHP 5 sẽ đưa ra các lỗi "không thể" khi bạn cố gắng gửi các tiêu đề sau BOM.
Piskvor rời khỏi tòa nhà

5
αβγ không phải là ascii, nhưng có thể xuất hiện trong các bảng mã 8 bit-ascii. Việc sử dụng BOM sẽ vô hiệu hóa benafit của utf-8, khả năng tương thích của nó với ascii (khả năng làm việc với các ứng dụng độ trễ khi sử dụng ascii thuần túy).
ctrl-alt-delor

1
Đây là câu trả lời sai. Một chuỗi có BOM ở phía trước nó là một thứ khác hoàn toàn. Nó không phải là ở đó và chỉ cần vít mọi thứ lên.
tchrist

Không có BOM, điều này sẽ mở ra như ANSI trong hầu hết các trình soạn thảo. Tôi hoàn toàn đồng ý. Nếu điều này xảy ra, bạn sẽ may mắn nếu bạn xử lý đúng Codepage nhưng thực sự đó chỉ là phỏng đoán, vì Codepage không phải là một phần của tệp. Một BOM là.
sáng

1

Dưới đây là kinh nghiệm của tôi với các yêu cầu kéo Visual Studio, Sourcetree và Bitbucket, điều này đã gây ra cho tôi một số vấn đề:

Vì vậy, hóa ra BOM có chữ ký sẽ bao gồm một ký tự chấm đỏ trên mỗi tệp khi xem xét yêu cầu kéo (nó có thể khá khó chịu).

Nhập mô tả hình ảnh ở đây

Nếu bạn di chuột lên nó, nó sẽ hiển thị một ký tự như "ufeff", nhưng hóa ra Sourcetree không hiển thị các loại phụ đề này, vì vậy rất có thể nó sẽ kết thúc trong các yêu cầu kéo của bạn, điều đó sẽ ổn vì đó là Visual Studio 2017 mã hóa các tệp mới ngay bây giờ, vì vậy có lẽ Bitbucket nên bỏ qua điều này hoặc làm cho nó hiển thị theo cách khác, thông tin thêm ở đây:

Dấu chấm màu đỏ BitBucket diff view


-4

UTF với BOM sẽ tốt hơn nếu bạn sử dụng UTF-8 trong các tệp HTML và nếu bạn sử dụng tiếng Serbia Cyrillic, tiếng Serbia Latin, tiếng Đức, tiếng Hungary hoặc một số ngôn ngữ kỳ lạ trên cùng một trang.

Đó là ý kiến ​​của tôi (30 năm trong ngành điện toán và CNTT).


1
Tôi thấy điều này cũng đúng. Nếu bạn sử dụng các ký tự bên ngoài bộ 255 ASCII đầu tiên và bạn bỏ qua BOM, các trình duyệt sẽ hiểu nó là ISO-8859-1 và bạn nhận được các ký tự bị cắt xén. Đưa ra các câu trả lời ở trên, điều này rõ ràng là trên các nhà cung cấp trình duyệt đã làm sai khi họ không phát hiện ra BOM. Nhưng trừ khi bạn làm việc tại Microsoft Edge / Mozilla / Webkit / Blink, bạn không có lựa chọn nào khác ngoài làm việc với những khiếm khuyết mà các ứng dụng này có.
asontu

UTF là gì? UTF-8? UTF-16? Thứ gì khác?
Peter Mortensen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.