Маркер последовательности байтов
Маркер последовательности байтов или метка порядка байтов (англ. Byte Order Mark, BOM) — специальный символ из стандарта Юникод, вставляемый в начало текстового файла или потока для обозначения того, что в файле (потоке) используется Юникод, а также для косвенного указания кодировки и порядка байтов, с помощью которых символы Юникода были закодированы. Номер этого символа в стандарте Юникод — U+FEFF
. Использование этого символа, согласно спецификации Юникод, не является обязательным, однако оно широко распространено, так как позволяет легко избежать неверного декодирования текстовой информации.
Использование
Согласно спецификации Юникода, маркер может стоять только в самом начале файла или потока. Если же символ U+FEFF
встречается в середине потока данных, он должен интерпретироваться как «нулевой ширины неразрывный пробел» (по существу, неотображаемый и ничего не меняющий символ). Однако, большинство[сколько?] браузеров, кроме Opera версий 12 и ниже, воспринимают BOM в середине документа как символ, занимающий целую строку, после чего генерируют перенос строки[1].
Для неразрывного пробела нулевой ширины в Юникоде есть и отдельный специальный символ — U+2060
, который и рекомендуется использовать в этом качестве, а маркер последовательности байтов U+FEFF
рекомендуется использовать только по своему прямому назначению.
Если формат представления символов Юникода точно известен принимающей программе заранее, то по стандарту Юникода маркер ставить не следует. И если формат объявлен другим способом (например, MIME в поле заголовка Content-Type
), маркер по стандарту ставить не полагается.
Определение кодировки по маркеру последовательности байтов
По тому, как закодирован маркер последовательности байтов, стоящий в начале файла или потока, можно легко определить кодировку и порядок байтов, использованные для кодирования символов Юникода во всём данном файле или потоке. Это обстоятельство в основном и явилось причиной широкого использования маркера последовательности байтов.
Кодировка | Представление маркера последовательности байтов | Представление маркера при ошибочном раскодировании другой кодировкой | |||||
---|---|---|---|---|---|---|---|
Шестнадцатеричный код | Десятичный код | ISO-8859-1 | KOI8-R | CP1251 | CP866 | комментарий | |
UTF-8[t 1] | EF BB BF |
239 187 191 |
 |
О╩© |
п»ї |
я╗┐ | |
UTF-16 (BE) | FE FF |
254 255 |
þÿ |
ЧЪ |
юя |
■ |
пробел — неразрывный |
UTF-16 (LE) | FF FE |
255 254 |
ÿþ |
ЪЧ |
яю |
■ | |
UTF-32 (BE) | 00 00 FE FF |
0 0 254 255 |
␀␀þÿ |
␀␀ЧЪ |
␀␀юя |
␀␀■ |
␀ — NUL, пробел — неразрывный |
UTF-32 (LE) | FF FE 00 00 |
255 254 0 0 |
ÿþ␀␀ |
ЪЧ␀␀ |
яю␀␀ |
■␀␀ | |
UTF-7[t 1] | 2B 2F 76 38 [t 2] |
43 47 118 56 |
+/v8 | ||||
UTF-1[t 1] | F7 64 4C |
247 100 76 |
÷dL | ||||
UTF-EBCDIC[t 1] | DD 73 66 73 |
221 115 102 115 |
Ýsfs | ||||
SCSU[t 1] | 0E FE FF [t 3] |
14 254 255 |
␎þÿ |
|
|
␎■ |
␎ — упр. символ Shift Out, пробел — неразрывный |
BOCU-1[t 1] | FB EE 28 |
251 238 40 |
ûî |
|
|
√ю( | |
GB-18030[t 1] | 84 31 95 33 |
132 49 149 51 |
�1�3 |
|
|
Д1Х3 |
� — коды без значений |
- В этих кодировках последовательность не определяет именно порядок байтов, так как кодировка однобайтная, но эта последовательность может использоваться для определения способа кодировки.[2][3]
- В UTF-7 в связи с использованием base-64, четвёртый байт BOM является
001111xx
в двоичном представлении, гдеxx
зависит от следующего символа (первого после BOM). Поэтому четвёртый байт не является только частью BOM, но также содержит информацию о следующем (не BOM) символе. Дляxx=00
,01
,10
,11
, четвёртый байт будет, соответственно,38
,39
,2B
, или2F
при кодировке в base64. Если же следующий символ не кодируется base64, то используется38
в качестве четвёртого байта, а следующий байт2D
. - SCSU предусматривает и другие кодировки для U+FEFF, указанная последовательность является рекомендованной в UTR #6.[4]
Сложности, которые необходимо учитывать при использовании маркера
Есть случаи, когда использования маркера последовательности байтов следует избегать, несмотря на удобства его применения. Например, использование маркера в веб-шаблонах вызывает появление пустых строк в документе, поэтому рекомендуется удалять маркер из веб-скриптов и CSS-файлов. А наличие маркера в начале файлов PHP (до тега <?php
) приводит к тому, что пустая строка отправляется клиенту ещё до начала выполнения кода, что вызывает сбой в тех случаях, когда клиенту должен сразу отправиться HTTP-заголовок (при переадресации запроса, например).[5] Также может неверно отрабатывать json_decode, если json записан в файл с BOM.
Примечания
- The byte-order mark (BOM) in HTML (англ.). www.w3.org. Дата обращения: 19 сентября 2018.
- FAQ - UTF-8, UTF-16, UTF-32 & BOM: Can a UTF-8 data stream contain the BOM character (in UTF-8 form)? If yes, then can I still assume the remaining UTF-8 bytes are in big-endian order? . Дата обращения: 4 января 2009. Архивировано 1 сентября 2012 года.
- STD 63: UTF-8, a transformation of ISO 10646 Byte Order Mark (BOM)
- UTR #6: Signature Byte Sequence for SCSU
- Potential issues with the UTF-8 BOM