Общее представление о Unicode, UTF-8, UTF-16 LE/BE, BOM
Unicode(далее юникод) — это стандарт, который определяет таблицу символов и способы машинного представления (кодировки) этих символов в байтах.
Таблица символов ставит каждому символу в соответствие значение в виде U+[число в шестнадцатиричной СС]. Например, U+0053 соответствует заглавной латинской букве S. Таблица unicode
Unicode содержит 1,114,112 символов в диапазоне от 0 до 10FFFF. Все символы разделены на 17 групп от группы 0 до 16.
Существуют следующие байтовые представления символов юникода UTF-8, UTF-16(UTF-16 LE или UTF-16 BE), UTF-32(UTF-32 LE или UTF-32 BE).
Каждая кодировка устанавливает свои правила преобразования символа юникод в байты и использует разное количество байтов для представления разных символов.
Например, кодировка UTF-8 использует от 1 до 4 байтов и позволяет покрыть все 1,114,112 символов юникода (потенциально даже больше символов). Первые 128 символов в таблице юникод совпадают с 128 символами из кодовой таблицы ASCII, и UTF-8 кодирует эти 128 символов так же, как и ASCII. В качестве байтового представления используется просто порядковый номер в таблице.
Ниже кусок юникод-таблицы, первые 128 символов, в ней представлены порядковый номер и символ
чтобы получить порядковый номер(U+xxxx) в таблице нужно к числу строки(0000, 0010, 0020, …, 0070) добавить номер столбца(0, 1, 2, …, F), например ‘K’ — это ‘U+004B’
порядковый номер в общем случае не является машинным представлением, но в случае первых 128 символов совпадает с байтовым кодом по версии ASCII и UTF-8
тут число не просто порядковый номер, а байтовое представление символа в памяти компьютера
кусок таблицы, всю можно посмотреть тут
Один символ кодировки UTF-16 представлен последовательностью двух байтов или двух пар байтов (т.е. 2 или 4 байта на символ). Получается, наименьшей единицей представления символа является 2 байта (называют “слово”). Который из двух байтов в слове идёт впереди, старший или младший, зависит от порядка байтов. Суффиксы BE и LE в названии кодировки указывают порядок. BE — big-endian — от старшего к младшему; LE — little-endian — от младшего к старшему.
Чтобы определить порядок байтов на основании самого файла, используется специальный юникод-символ U+FEFF, называемый BOM (Byte Order Mark), меткой последовательности байтов. Символ U+FEFF добавляется в начало текстового файла, считав который можно определить кодировку файла.
Как видно из таблицы
- UTF-8 c BOM записывает в начало файла метку U+FEFF в виде 3-х байтов EF BB BF
- UTF-16 BE c BOM записывает в начало файла метку U+FEFF в виде 2-х байтов FE FF
- UTF-16 LE c BOM записывает в начало файла метку U+FEFF в виде 2-х байтов FF FE
Согласно стандарту Encoding Standard, UTF-8 является самой подходящей кодировкой для обмена юникодом.
Unicode в операционных системах
Современные ОС более менее поддерживают юникод.
К примеру, ОС семейства Windows NT, а точнее с Windows 2000, поддерживают ввод и вывод символов юникод. Для байтового представления символов юникод используется UTF-16 LE. При этом Windows не ограничивает прикладные программы касательно кодирования текстовых файлов, позволяя им использовать как UTF-16 LE, так и UTF-16 BE посредством установки и последующей трактовки метки последовательности байтов. Однако внутренний формат Windows — это UTF-16 LE.
Unix-подобные ОС, в том числе GNU/Linux, BSD, OS X, используют для представления юникода кодировку UTF-8.
Заметки сисадмина о интересных вещах из мира IT, инструкции и рецензии. Настраиваем Компьютеры/Сервера/1С/SIP-телефонию в Москве
UTF-8 vs UTF-8 без BOM — что когда использовать?
Маркер последовательности байтов или метка порядка байтов (англ. Byte Order Mark (BOM)) — Юникод-символ, используемый для индикации порядка байтов текстового файла. Его кодовый символ U+FEFF. По спецификации, его использование не является обязательным, однако, если маркер последовательности байтов используется, то он должен быть установлен в начале текстового файла. Помимо своего конкретного использования в качестве указателя порядка байтов, символ может также указать, какой кодировкой Unicode закодирован текст.
Кодировка Unicode может использовать 16-разрядные или 32-разрядные числа и приложение должно знать, как дальше с ними поступать. Поэтому потребность в маркере последовательности байтов возникает при обмене документами.
Различий никаких нет, кроме наличия/отсутствия маркера. Кодировка одна и та же – utf-8. По стандарту unicode маркер должен быть.
Удалять маркер BOM при сохранении нужно только для PHP, который почему-то не умеет корректно обрабатывать нормальные unicode файлы.
UTF-8 vs UTF-8 без BOM — что когда использовать?
Помогите, пожалуйста, разобраться:
UTF-8 и UTF-8 без BOM — в чём разница в использовании? Что лучше использовать для сохранения файлов?
Когда-то у меня сложилось впечатление, что UTF-8 универсальнее, лучше использовать эту кодировку — тогда я имел дело с HTML, CSS +/- JavaScript, но позднее — имея дело с PHP — получил опыт, говорящий, что UTF-8 без BOM предпочтительнее (были проблемы, как раз, из-за UTF-8)
Так, как всё-таки быть? Что использовать?
Мой опыт пока такой: для клиентской части — UTF-8 (либо нет разницы), для серверной — UTF-8 без BOM — всё так? Почему?
- Вопрос задан более трёх лет назад
- 55821 просмотр
- Вконтакте
Различий никаких нет, кроме наличия/отсутствия маркера. Кодировка одна и та же — utf-8. По стандарту unicode маркер должен быть.
Удалять маркер BOM при сохранении нужно только для PHP, который почему-то не умеет корректно обрабатывать нормальные unicode файлы.
- Вконтакте

Маркер последовательности байтов или метка порядка байтов (англ. Byte Order Mark (BOM)) — Юникод-символ, используемый для индикации порядка байтов текстового файла. Его кодовый символ U+FEFF. По спецификации, его использование не является обязательным, однако, если маркер последовательности байтов используется, то он должен быть установлен в начале текстового файла. Помимо своего конкретного использования в качестве указателя порядка байтов, символ может также указать, какой кодировкой Unicode закодирован текст.
Кодировка Unicode может использовать 16-разрядные или 32-разрядные числа и приложение должно знать, как дальше с ними поступать. Поэтому потребность в маркере последовательности байтов возникает при обмене документами.
Если сохраняете php файл — то без BOM, в остальном же разницы никакой не имеет.
What's the difference between UTF-8 and UTF-8 with BOM?
What’s different between UTF-8 and UTF-8 with BOM? Which is better?
![]()
22 Answers 22
The UTF-8 BOM is a sequence of bytes at the start of a text stream ( 0xEF, 0xBB, 0xBF ) that allows the reader to more reliably guess a file as being encoded in UTF-8.
Normally, the BOM is used to signal the endianness of an encoding, but since endianness is irrelevant to UTF-8, the BOM is unnecessary.
According to the Unicode standard, the BOM for UTF-8 files is not recommended:
2.6 Encoding Schemes
. Use of a BOM is neither required nor recommended for UTF-8, but may be encountered in contexts where UTF-8 data is converted from other encoding forms that use a BOM or where the BOM is used as a UTF-8 signature. See the “Byte Order Mark” subsection in Section 16.8, Specials, for more information.
![]()
The other excellent answers already answered that:
- There is no official difference between UTF-8 and BOM-ed UTF-8
- A BOM-ed UTF-8 string will start with the three following bytes. EF BB BF
- Those bytes, if present, must be ignored when extracting the string from the file/stream.
But, as additional information to this, the BOM for UTF-8 could be a good way to «smell» if a string was encoded in UTF-8. Or it could be a legitimate string in any other encoding.
For example, the data [EF BB BF 41 42 43] could either be:
- The legitimate ISO-8859-1 string «ï»¿ABC»
- The legitimate UTF-8 string «ABC»
So while it can be cool to recognize the encoding of a file content by looking at the first bytes, you should not rely on this, as show by the example above
Encodings should be known, not divined.
![]()
There are at least three problems with putting a BOM in UTF-8 encoded files.
- Files that hold no text are no longer empty because they always contain the BOM.
- Files that hold text within the ASCII subset of UTF-8 are no longer themselves ASCII because the BOM is not ASCII, which makes some existing tools break down, and it can be impossible for users to replace such legacy tools.
- It is not possible to concatenate several files together because each file now has a BOM at the beginning.
And, as others have mentioned, it is neither sufficient nor necessary to have a BOM to detect that something is UTF-8:
- It is not sufficient because an arbitrary byte sequence can happen to start with the exact sequence that constitutes the BOM.
- It is not necessary because you can just read the bytes as if they were UTF-8; if that succeeds, it is, by definition, valid UTF-8.
![]()
Here are examples of the BOM usage that actually cause real problems and yet many people don’t know about it.
BOM breaks scripts
Shell scripts, Perl scripts, Python scripts, Ruby scripts, Node.js scripts or any other executable that needs to be run by an interpreter — all start with a shebang line which looks like one of those:
It tells the system which interpreter needs to be run when invoking such a script. If the script is encoded in UTF-8, one may be tempted to include a BOM at the beginning. But actually the "#!" characters are not just characters. They are in fact a magic number that happens to be composed out of two ASCII characters. If you put something (like a BOM) before those characters, then the file will look like it had a different magic number and that can lead to problems.
The shebang characters are represented by the same two bytes in extended ASCII encodings, including UTF-8, which is commonly used for scripts and other text files on current Unix-like systems. However, UTF-8 files may begin with the optional byte order mark (BOM); if the "exec" function specifically detects the bytes 0x23 and 0x21, then the presence of the BOM (0xEF 0xBB 0xBF) before the shebang will prevent the script interpreter from being executed. Some authorities recommend against using the byte order mark in POSIX (Unix-like) scripts,[14] for this reason and for wider interoperability and philosophical concerns. Additionally, a byte order mark is not necessary in UTF-8, as that encoding does not have endianness issues; it serves only to identify the encoding as UTF-8. [emphasis added]
BOM is illegal in JSON
Implementations MUST NOT add a byte order mark to the beginning of a JSON text.
BOM is redundant in JSON
Not only it is illegal in JSON, it is also not needed to determine the character encoding because there are more reliable ways to unambiguously determine both the character encoding and endianness used in any JSON stream (see this answer for details).
BOM breaks JSON parsers
Not only it is illegal in JSON and not needed, it actually breaks all software that determine the encoding using the method presented in RFC 4627:
Determining the encoding and endianness of JSON, examining the first four bytes for the NUL byte:
Now, if the file starts with BOM it will look like this:
- UTF-32BE doesn’t start with three NULs, so it won’t be recognized
- UTF-32LE the first byte is not followed by three NULs, so it won’t be recognized
- UTF-16BE has only one NUL in the first four bytes, so it won’t be recognized
- UTF-16LE has only one NUL in the first four bytes, so it won’t be recognized
Depending on the implementation, all of those may be interpreted incorrectly as UTF-8 and then misinterpreted or rejected as invalid UTF-8, or not recognized at all.
Additionally, if the implementation tests for valid JSON as I recommend, it will reject even the input that is indeed encoded as UTF-8, because it doesn’t start with an ASCII character < 128 as it should according to the RFC.
Other data formats
BOM in JSON is not needed, is illegal and breaks software that works correctly according to the RFC. It should be a nobrainer to just not use it then and yet, there are always people who insist on breaking JSON by using BOMs, comments, different quoting rules or different data types. Of course anyone is free to use things like BOMs or anything else if you need it — just don’t call it JSON then.
For other data formats than JSON, take a look at how it really looks like. If the only encodings are UTF-* and the first character must be an ASCII character lower than 128 then you already have all the information needed to determine both the encoding and the endianness of your data. Adding BOMs even as an optional feature would only make it more complicated and error prone.
Other uses of BOM
As for the uses outside of JSON or scripts, I think there are already very good answers here. I wanted to add more detailed info specifically about scripting and serialization, because it is an example of BOM characters causing real problems.
What’s different between UTF-8 and UTF-8 without BOM?
Short answer: In UTF-8, a BOM is encoded as the bytes EF BB BF at the beginning of the file.
Originally, it was expected that Unicode would be encoded in UTF-16/UCS-2. The BOM was designed for this encoding form. When you have 2-byte code units, it’s necessary to indicate which order those two bytes are in, and a common convention for doing this is to include the character U+FEFF as a «Byte Order Mark» at the beginning of the data. The character U+FFFE is permanently unassigned so that its presence can be used to detect the wrong byte order.
UTF-8 has the same byte order regardless of platform endianness, so a byte order mark isn’t needed. However, it may occur (as the byte sequence EF BB FF ) in data that was converted to UTF-8 from UTF-16, or as a «signature» to indicate that the data is UTF-8.
Without. As Martin Cote answered, the Unicode standard does not recommend it. It causes problems with non-BOM-aware software.
A better way to detect whether a file is UTF-8 is to perform a validity check. UTF-8 has strict rules about what byte sequences are valid, so the probability of a false positive is negligible. If a byte sequence looks like UTF-8, it probably is.
![]()
![]()
UTF-8 with BOM is better identified. I have reached this conclusion the hard way. I am working on a project where one of the results is a CSV file, including Unicode characters.
If the CSV file is saved without a BOM, Excel thinks it’s ANSI and shows gibberish. Once you add "EF BB BF" at the front (for example, by re-saving it using Notepad with UTF-8; or Notepad++ with UTF-8 with BOM), Excel opens it fine.
Prepending the BOM character to Unicode text files is recommended by RFC 3629: "UTF-8, a transformation format of ISO 10646", November 2003 at https://www.rfc-editor.org/rfc/rfc3629 (this last info found at: http://www.herongyang.com/Unicode/Notepad-Byte-Order-Mark-BOM-FEFF-EFBBBF.html)
Question: What’s different between UTF-8 and UTF-8 without a BOM? Which is better?
Here are some excerpts from the Wikipedia article on the byte order mark (BOM) that I believe offer a solid answer to this question.
On the meaning of the BOM and UTF-8:
The Unicode Standard permits the BOM in UTF-8, but does not require or recommend its use. Byte order has no meaning in UTF-8, so its only use in UTF-8 is to signal at the start that the text stream is encoded in UTF-8.
Argument for NOT using a BOM:
The primary motivation for not using a BOM is backwards-compatibility with software that is not Unicode-aware. Another motivation for not using a BOM is to encourage UTF-8 as the «default» encoding.
Argument FOR using a BOM:
The argument for using a BOM is that without it, heuristic analysis is required to determine what character encoding a file is using. Historically such analysis, to distinguish various 8-bit encodings, is complicated, error-prone, and sometimes slow. A number of libraries are available to ease the task, such as Mozilla Universal Charset Detector and International Components for Unicode.
Programmers mistakenly assume that detection of UTF-8 is equally difficult (it is not because of the vast majority of byte sequences are invalid UTF-8, while the encodings these libraries are trying to distinguish allow all possible byte sequences). Therefore not all Unicode-aware programs perform such an analysis and instead rely on the BOM.
In particular, Microsoft compilers and interpreters, and many pieces of software on Microsoft Windows such as Notepad will not correctly read UTF-8 text unless it has only ASCII characters or it starts with the BOM, and will add a BOM to the start when saving text as UTF-8. Google Docs will add a BOM when a Microsoft Word document is downloaded as a plain text file.
On which is better, WITH or WITHOUT the BOM:
The IETF recommends that if a protocol either (a) always uses UTF-8, or (b) has some other way to indicate what encoding is being used, then it “SHOULD forbid use of U+FEFF as a signature.”
My Conclusion:
Use the BOM only if compatibility with a software application is absolutely essential.
Also note that while the referenced Wikipedia article indicates that many Microsoft applications rely on the BOM to correctly detect UTF-8, this is not the case for all Microsoft applications. For example, as pointed out by @barlop, when using the Windows Command Prompt with UTF-8 † , commands such type and more do not expect the BOM to be present. If the BOM is present, it can be problematic as it is for other applications.
† The chcp command offers support for UTF-8 (without the BOM) via code page 65001.