Яка різниця між UTF-8 та UTF-8 без BOM?


818

Що відрізняється між UTF-8 та UTF-8 без BOM ? Який краще?


77
UTF-8 може бути автоматично виявлений краще за вмістом, ніж BOM. Метод простий: спробуйте прочитати файл (або рядок) як UTF-8, і якщо це вдалося, припустіть, що дані є UTF-8. В іншому випадку припустимо, що це CP1252 (або якесь 8-бітове кодування). Будь-яке восьми бітове кодування, яке не є UTF-8, майже напевно міститиме послідовності, заборонені UTF-8. Чистий ASCII (7 біт) трактується як UTF-8, але результат також правильний.
Tronic

39
Сканування великих файлів на вміст UTF-8 вимагає часу. BOM робить цей процес набагато швидшим. На практиці вам часто потрібно робити і те, і інше. Винуватець сьогодні в тому, що все ще багато текстового вмісту не є Unicode, і я все ще натрапляю на інструменти, які говорять про те, що вони роблять Unicode (наприклад, UTF-8), але видають їхній вміст іншою кодовою сторінкою.
Jeroen Wiert Pluimers

10
@Tronic Я не думаю, що в цьому випадку "краще" . Це залежить від навколишнього середовища. Якщо ви впевнені, що всі файли UTF-8 позначені BOM, ніж перевірка BOM - це "кращий" спосіб, оскільки він швидший і надійніший.
mg30rg

32
UTF-8 не має BOM. Коли ви ставите кодову точку U + FEFF на початку файлу UTF-8, слід особливо уважно ставитися до цього. Це лише одна з тих брехней, які називають Microsoft, як, наприклад, називати кодування "Unicode", коли такого немає.
tchrist

7
"Сучасний мейнфрейм (і AIX) є мало ендіанським, що знає UTF-8 " UTF-8 не має кінця ! немає перетасування байтів навколо, щоб поставити пари чи групи з чотирьох у правильний "порядок" для певної системи! Для виявлення послідовності байт UTF-8 може бути корисним зауважити, що перший байт багатобайтової послідовності "кодова точка" (байти, які НЕ є "звичайними" ASCII) має встановлений біт MS і всі один-три більше послідовно менш значущі біти з подальшим розрядом скидання. Загальна кількість цих наборів є на один менший байт, який знаходиться в цій
кодовій точці,

Відповіді:


773

BT UTF-8 - це послідовність байтів на початку текстового потоку ( 0xEF, 0xBB, 0xBF), що дозволяє читачеві більш надійно відгадати файл як закодований в UTF-8.

Зазвичай, BOM використовується для сигналізації про витривалість кодування, але оскільки ендіансність не має значення для UTF-8, BOM не є необхідним.

Відповідно до стандарту Unicode , BOM для файлів UTF-8 не рекомендується :

2.6 Схеми кодування

... Використання BOM не потрібно і не рекомендується для UTF-8, але може зустрічатися в контекстах, коли дані UTF-8 перетворюються з інших форм кодування, які використовують BOM або де BOM використовується як підпис UTF-8 . Додаткову інформацію див. У підрозділі «Позначка порядку байтів» у Розділі 16.8 .


114
Це може бути не рекомендовано, але, з мого досвіду конверсії на івриті, BOM іноді має вирішальне значення для розпізнавання UTF-8 в Excel, і може змінити значення між Jibrish та Hebrew
Матанія

26
Це може бути не рекомендовано, але це робило чудеса моєму сценарію повноважень при спробі вивести "æøå"
Маріус

63
Незважаючи на те, що стандарт його не рекомендує, це дозволено, і я дуже вважаю за краще щось мати роль підпису UTF-8, а не альтернативи припущення чи здогадки. Програмне забезпечення, сумісне з Unicode, повинне / повинно вміти боротися з його наявністю, тому я особисто заохочую його використання.
мартіно

30
@ bames53: Так, в ідеальному світі зберігання кодування текстових файлів як метаданих файлової системи було б кращим способом зберегти її. Але більшість із нас, що живуть у реальному світі, не можуть змінити файлову систему ОС (-ів), що наші програми запускаються - тому використання підпису BOM, незалежного від платформи стандарту Unicode, є найкращою і найбільш практичною альтернативою IMHO.
martineau

34
@martineau Щойно вчора я наткнувся на файл із BOM UTF-8, який не був UTF-8 (це був CP936). Прикро, що ті, хто відповідає за величезну кількість болю, спричиненої групою UTF-8, значною мірою про це не звертають уваги.
bames53

243

Інші чудові відповіді вже відповіли, що:

  • Офіційної різниці між UTF-8 та BOM-ed UTF-8 немає
  • Рядок UTF-8 з BOM-ed почнеться з трьох наступних байтів. EF BB BF
  • Ці байти, якщо вони є, потрібно ігнорувати при витягуванні рядка з файлу / потоку.

Але, як додаткова інформація до цього, BOM для UTF-8 може бути хорошим способом "запаху", якщо рядок була закодована в UTF-8 ... Або це може бути законною рядком у будь-якому іншому кодуванні ...

Наприклад, дані [EF BB BF 41 42 43] можуть бути:

  • Законний рядок ISO-8859-1 "ï» ¿ABC "
  • Легітимний рядок UTF-8 "ABC"

Тому, хоча можна розпізнати кодування вмісту файлу, переглянувши перші байти, не можна покладатися на це, як показує приклад вище

Кодування повинні бути відомими, а не дозволеними.


60
@Alcott: Ви правильно зрозуміли. Рядок [EF BB BF 41 42 43] - це лише купа байтів. Вам потрібна зовнішня інформація, щоб вибрати, як її інтерпретувати. Якщо ви вважаєте, що ці байти були закодовані за допомогою ISO-8859-1, то рядок є "ï» ¿ABC ". Якщо ви вважаєте, що ці байти були закодовані за допомогою UTF-8, то це "ABC". Якщо ви не знаєте, то потрібно спробувати це з'ясувати. BOM може бути підказкою. Відсутність недійсного символу при розшифровці як UTF-8 може бути іншим ... Зрештою, якщо ви не зможете якось запам'ятати / знайти кодування, масив байтів - це лише масив байтів.
paercebal

19
@paercebal Хоча "ï» ¿"є дійсним латиніною-1, дуже малоймовірно, що текстовий файл починається з цієї комбінації. Те ж саме стосується ucs2-le / бути маркерами ÿþ і þÿ. Також ви ніколи не можете знати.
користувач877329

16
@deceze Це, ймовірно, лінгвістично недійсне: Спочатку ï (що нормально), потім якийсь лапки без проміжку (не ок). ¿Вказує, що це іспанська мова, але ï не використовується в іспанській мові. Висновок: це не латинь-1 із визначеністю, що значно вище визначеності без нього.
user877329

20
@user Звичайно, це не обов'язково має сенс. Але якщо ваша система покладається на здогадки , тут виникають невизначеності. Деякі зловмисники спеціально подають текст, починаючи з цих 3 букв, і ваша система раптом припускає, що він дивиться на UTF-8 з BOM, трактує текст як UTF-8, де він повинен використовувати латинську-1, і відбувається деяка ін'єкція Unicode. Просто гіпотетичний приклад, але, безумовно, можливий. Ви не можете судити про кодування тексту за його змістом, періодом.
деге

40
"Кодування повинно бути відомим, а не розкритим." Серце і душа проблеми. +1, добрий пане. Іншими словами: або стандартизуйте свій вміст і скажіть: "Ми завжди використовуємо це кодування. Період. Напишіть це так. Читайте так", або розробіть розширений формат, який дозволяє зберігати кодування як метадані. (Останньому, мабуть, також потрібне «стандартне кодування для завантажувального програмного забезпечення».
Скажімо,

135

Принаймні три проблеми із введенням BOM у файли, кодовані UTF-8.

  1. Файли, які не містять тексту, більше не порожні, оскільки вони завжди містять BOM.
  2. Файли, що містять текст, що знаходиться в підмножині ASCII UTF-8, вже не є ASCII, оскільки BOM не є ASCII, через що деякі існуючі інструменти руйнуються, і користувачі можуть бути неможливими замінити такі застарілі інструменти.
  3. З’єднати кілька файлів разом неможливо, оскільки кожен файл тепер має BOM на початку.

І, як уже згадували інші, не достатньо і не потрібно мати BOM, щоб виявити, що щось є UTF-8:

  • Це недостатньо, тому що довільна послідовність байтів може трапитися з тієї точної послідовності, що становить BOM.
  • Це не обов'язково, оскільки ви можете просто читати байти так, ніби вони були UTF-8; якщо це вдасться, це, за визначенням, дійсне UTF-8.

8
Повторний пункт 1 "Файли, які не містять тексту, більше не порожні, оскільки вони завжди містять BOM", це (1) пов'язує рівень файлової системи ОС з інтерпретованим рівнем вмісту, плюс це (2) неправильно передбачає, що за допомогою BOM потрібно поставити BOM також у кожному інакше порожньому файлі. Практичне рішення (1) - не робити (2). По суті, скарга зводиться до "можна непрактично помістити BOM в інакше порожній файл, тим самим запобігаючи найпростішому виявленню логічно порожнього файлу (перевіряючи розмір файлу)". Але все-таки хороше програмне забезпечення повинно мати можливість з цим боротися, оскільки воно має мету.
ура та хт. - Альф

7
З точки зору 2, "Файли, що містять текст ASCII, більше не є ASCII", це пов'язує ASCII з UTF-8. Файл UTF-8, який містить текст ASCII, не є ASCII, це UTF-8. Аналогічно, файл UTF-16, який містить текст ASCII, не є ASCII, це UTF-16. І так далі. ASCII - це 7-бітний однобайтовий код. UTF-8 - це 8-бітове розширення довжини ASCII. Якщо "інструменти виходять з ладу" через> 127 значень, вони просто не підходять для 8-бітового світу. Одне просте практичне рішення - використовувати лише файли ASCII з інструментами, які розбиваються на значення, що не мають ASCII байтів. Можливо, кращим рішенням є виривання цих недобрих інструментів.
ура та хт. - Альф

8
Звернення до пункту 3 "Неможливо об'єднати кілька файлів разом, тому що кожен файл має BOM на початку" - це просто неправильно. У мене немає проблем з об'єднанням файлів UTF-8 з BOM, тому це однозначно можливо. Я думаю, можливо, ти мав на увазі, що Unix-land catне дасть тобі чистого результату, результат, який має BOM лише на старті. Якщо ви це мали на увазі, то це тому, що catпрацює на рівні байтів, а не на рівні інтерпретованого вмісту, і подібним чином catне можу мати справу з фотографіями. Але це не приносить великої шкоди. Це тому, що BOM кодує нерозривний простір нульової ширини.
ура та хт. - Альф

20
@ Cheersandhth.-Alf Ця відповідь правильна. Ви просто вказуєте на помилки Microsoft.
tchrist

9
@brighty: Ситуація не покращується, додавши бомбу.
Дедуплікатор

84

Ось приклади використання BOM, які насправді викликають реальні проблеми, але багато людей про це не знають.

BOM розбиває сценарії

Сценарії оболонки, скрипти Perl, сценарії Python, скрипти Ruby, скрипти Node.js або будь-який інший виконуваний файл, який повинен запускати інтерпретатор - все починається з рядка shebang, який виглядає як один із таких:

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

Він повідомляє системі, якого інтерпретатора потрібно запустити, коли викликає такий сценарій. Якщо сценарій кодується в UTF-8, можливо, спокуса включити BOM на початку. Але насправді "#!" символи - це не просто символи. Насправді вони є магічним числом , яке складається з двох символів ASCII. Якщо ви поставите щось (наприклад, BOM) перед цими символами, то файл виглядатиме так, що він мав інше магічне число, і це може призвести до проблем.

Дивіться Вікіпедію, статтю: Shebang, розділ: Чарівне число :

Символи shebang представлені тими ж двома байтами в розширених кодуваннях ASCII, включаючи UTF-8, який зазвичай використовується для сценаріїв та інших текстових файлів у поточних системах, схожих на Unix. Однак файли UTF-8 можуть починатися з необов'язкової позначки порядку байти (BOM); якщо функція "exec" спеціально виявляє байти 0x23 та 0x21, то наявність BOM (0xEF 0xBB 0xBF) перед шебангом не дозволить виконувати інтерпретатор сценарію.Деякі органи влади рекомендують забороняти використовувати позначку порядку байтів у сценаріях POSIX (подібних Unix) [14] з цієї причини та для ширшої інтероперабельності та філософських проблем. Додатково, марка порядку байтів не є необхідною в UTF-8, оскільки кодування не має проблем із витримкою; він служить лише для ідентифікації кодування як UTF-8. [наголос додано]

BOM є незаконним у JSON

Див. RFC 7159, Розділ 8.1 :

Реалізації НЕ МОЖЕ додавати позначку порядку байтів на початок тексту JSON.

BOM є зайвим у JSON

Він не тільки є незаконним у JSON, він також не потрібен для визначення кодування символів, оскільки існують більш надійні способи однозначного визначення кодування символів та ендіанності, що використовуються в будь-якому потоці JSON ( детальну інформацію див. У цій відповіді ).

BOM ламає парсер JSON

Він не тільки незаконний у JSON і не потрібен , він фактично порушує все програмне забезпечення, яке визначає кодування, використовуючи метод, представлений в RFC 4627 :

Визначення кодування та витривалості JSON, вивчення перших чотирьох байт байта 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

Тепер, якщо файл починається з BOM, він буде виглядати приблизно так:

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

Зауважте, що:

  1. UTF-32BE не починається з трьох NUL, тому він не буде розпізнаний
  2. UTF-32LE перший байт не супроводжується трьома NUL, тому він не буде розпізнаний
  3. UTF-16BE має лише один NUL у перших чотирьох байтах, тому він не буде розпізнаний
  4. UTF-16LE має лише один NUL у перших чотирьох байтах, тому він не буде розпізнаний

Залежно від реалізації, все це може трактуватися неправильно як UTF-8, а потім неправильно трактуватися або відкидатися як недійсне UTF-8 або взагалі не визнаватися.

Крім того, якщо тести реалізації для дійсного JSON, як я рекомендую, він відхилить навіть вхід, який дійсно закодований як UTF-8, оскільки він не починається з символу ASCII <128, як слід згідно з RFC.

Інші формати даних

BOM в JSON не потрібен, є незаконним і порушує програмне забезпечення, яке працює правильно відповідно до RFC. Це повинен бути нобілайзер, щоб просто не використовувати його тоді, і все ж, завжди є люди, які наполягають на порушенні JSON за допомогою BOMs, коментарів, різних правил цитування або різних типів даних. Звичайно, кожен може вільно користуватися такими речами, як BOM або що-небудь інше, якщо вам це потрібно - просто не називайте це JSON тоді.

Для інших форматів даних, ніж JSON, подивіться, як це насправді виглядає. Якщо єдиними кодуваннями є UTF- *, а перший символ повинен бути символом ASCII нижче 128, то у вас вже є вся інформація, необхідна для визначення як кодування, так і цілеспрямованості ваших даних. Додавання BOMs навіть як додаткова функція лише ускладнить його і схильний до помилок.

Інші види використання BOM

Щодо використання поза JSON або сценаріїв, я думаю, тут вже є дуже хороші відповіді. Я хотів додати більш детальну інформацію, зокрема про сценарії та серіалізацію, тому що це приклад символів BOM, що викликають реальні проблеми.


5
rfc7159, який замінює rfc4627 насправді говорить про підтримку BOM, може бути не таким злим. В основному відсутність BOM - це лише неоднозначне хитрості, тому старе програмне забезпечення Windows і Unix, яке не обізнане з Unicode, все ще може обробляти utf-8.
Ерік Грандж

2
Здається, що JSON потребує оновлення, щоб підтримати його, як і сценарії Perl, сценарії Python, сценарії Ruby, Node.js. Тільки тому, що ці платформи вирішили не включати підтримку, не обов'язково вбивають використання для BOM. Apple вже кілька років намагається вбити Adobe, а Adobe все ще існує. Але просвітницький пост.
htm11h

13
@EricGrange, ви, здається, дуже наполегливо підтримуєте BOM, але не усвідомлюєте, що це призведе до того, що всебічний, універсально корисний, оптимально-мінімальний формат "простого тексту" є реліктом минулого до UTF8! Додавання будь-якого (в діапазоні) заголовка до простого текстового потоку, за визначенням, нав'язує обов'язковий протокол до найпростіших текстових файлів, що робить його ніколи більше "найпростішим"! А для чого виграш? Щоб підтримувати всі інші стародавні кодування CP, які також не мали підписів, тож ви можете помилити їх з UTF-8? (BTW, ASCII теж UTF-8. Так, BOM для тих теж?;) Давай.)
Sz.

2
Ця відповідь є причиною, чому я підійшов до цього питання! Я створюю свої bash-скрипти в Windows і відчуваю багато проблем при публікації цих скриптів в Linux! Те ж саме і з файлами Jason.
Тоно Нам

2
Я хотів би, щоб я міг проголосувати цю відповідь близько п'ятдесяти разів. Я також хочу додати, що на даний момент UTF-8 перемогла у війні за стандарти, і майже весь текст, що випускається в Інтернеті, є UTF-8. Деякі з найпопулярніших мов програмування (наприклад, C # та Java) використовують UTF-16 всередині, але коли програмісти, які використовують ці мови, записують файли для виведення потоків, вони майже завжди кодують їх як UTF-8. Тому більше не має сенсу мати BOM для позначення файлу UTF-8; UTF-8 має бути типовим типом, який ти використовуєш під час читання, і спробувати інші кодування лише у випадку, якщо декодування UTF-8 не вдалося.
rmunn

51

Що відрізняється між UTF-8 та UTF-8 без BOM?

Коротка відповідь: У UTF-8 BOM кодується як байти EF BB BFна початку файлу.

Довга відповідь:

Спочатку очікувалося, що Unicode буде закодований в UTF-16 / UCS-2. BOM був розроблений для цієї форми кодування. Коли у вас є 2-байтні одиниці коду, необхідно вказати, в якому порядку вони знаходяться ці два байти, і загальним умовою для цього є включення символу U + FEFF як "Марка порядку байтів" на початку даних. Символ U + FFFE назавжди не призначений, щоб його наявність могла використовуватися для виявлення неправильного порядку байтів.

UTF-8 має той самий порядок байтів незалежно від витривалості платформи, тому позначка порядку байтів не потрібна. Однак може траплятися (як послідовність байтів EF BB FF) у даних, які були перетворені в UTF-8 з UTF-16, або як "підпис", щоб вказати, що дані є UTF-8.

Який краще?

Без. Як відповів Мартін Кот, стандарт Unicode не рекомендує цього. Це спричиняє проблеми із програмним забезпеченням, яке не знає BOM.

Кращим способом виявити, чи є файл UTF-8, є перевірка дійсності. UTF-8 має суворі правила щодо того, які послідовності байтів є дійсними, тому ймовірність помилкового додатника незначна. Якщо послідовність байтів схожа на UTF-8, це, мабуть, так.


8
це також призведе до недійсності дійсного UTF-8 з єдиним помилковим байтом, хоча: /
endolith

8
-1 re "Це спричиняє проблеми із програмним забезпеченням, яке не знає BOM". Це ніколи для мене не було проблемою, а навпаки, відсутність BOM викликає проблеми з програмним забезпеченням, відомим BOM (зокрема Visual C ++). проблема. Тож ця заява дуже специфічна для платформи , вузька точка зору Unix, але оману подається так, ніби вона застосовується взагалі. Якого немає.
ура та хт. - Альф

6
Ні, UTF-8 не має BOM. Ця відповідь невірна. Див. Стандарт Unicode.
tchrist

2
Ви навіть можете подумати, що у вас є чистий файл ASCII, лише дивлячись на байти. Але це також може бути файл utf-16, де вам доведеться дивитися на слова, а не на байти. Сучасне програмне забезпечення повинно знати про BOM. Прочитати utf-8 все-таки може не вдається, якщо виявити недійсні послідовності, кодові точки, які можуть використовувати меншу послідовність або кодові точки, які є сурогатами. Для utf-16 читання теж може бути невдалим, якщо є сироти-сурогати.
яскравий

1
@Alf, я не погоджуюся з вашою інтерпретацією ставлення, яке не стосується BOM, як " конкретної платформи , вузької точки зору Unix-Land". Для мене єдиним способом, який міг би придумати "Unix land", було б, якщо MS та Visual C ++ прийшли раніше * NIX, чого вони не зробили. Той факт , що MS (я припускаю , свідомо) почав використовувати BOM в UTF-8 , а не UTF-16 , підказує мені , що вони сприяли порушенню sh, perl, g++і багатьом іншим безкоштовним і потужних інструментів. Хочете, щоб справи працювали? Просто придбайте версії MS. MS створили специфічну для платформи проблему так само, як і катастрофа їх діапазону \ x80- \ x95.
bballdave025

30

UTF-8 з BOM краще ідентифікувати. Я дійшов цього висновку важким шляхом. Я працюю над проектом, де одним із результатів є файл CSV , включаючи символи Unicode.

Якщо файл CSV зберігається без BOM, Excel вважає, що це ANSI, і показує хитрість. Після додавання "EF BB BF" спереду (наприклад, повторне збереження за допомогою блокнота з UTF-8; або блокнота ++ з UTF-8 з BOM) Excel відкриває його нормально.

Попередження символу BOM до текстових файлів Unicode рекомендується RFC 3629: "UTF-8, формат перетворення ISO 10646", листопад 2003 року на http://tools.ietf.org/html/rfc3629 (остання інформація знайдена за адресою: http://www.herongyang.com/Unicode/Notepad-Byte-Order-Mark-BOM-FEFF-EFBBBF.html )


6
Дякуємо за чудову пораду, якщо ви створюєте файли UTF-8 для використання Excel. За інших обставин я все-таки слідкую за іншими відповідями і пропускаю БОМ.
barfuin

5
Це також корисно, якщо ви створюєте файли, які містять лише ASCII, а пізніше можуть бути додані до нього non-ascii. Я щойно стикався з такою проблемою: програмне забезпечення, яке очікує utf8, створює файл з деякими даними для редагування користувача. Якщо початковий файл містить лише ASCII, відкривається в деяких редакторах і потім зберігається, він закінчується латиною-1 і все порушується. Якщо я додам BOM, редактор виявить його як UTF8 і все працює.
Роберто Альсіна

1
Я знайшов кілька інструментів, пов'язаних з програмуванням, які вимагають, щоб BOM правильно розпізнавав файли UTF-8. Visual Studio, SSMS, SoureTree ....
kjbartel

5
Де ви читаєте рекомендацію щодо використання BOM в цьому RFC? У кращому випадку є настійна рекомендація не забороняти це за певних обставин, коли це зробити важко.
Дедуплікатор

8
Excel вважає, що це ANSI і показує хитрість, тоді проблема полягає в Excel.
Ісаак

17

BOM схиляється до бурхливості (не каламбур призначений (sic)) десь, десь. А коли він буває (наприклад, не розпізнається браузерами, редакторами тощо), він відображається як дивні символи на початку документа (наприклад, HTML-файл, відповідь JSON , RSS тощо). і спричиняє такі збентеження, як нещодавнє питання кодування, що виник під час розмови Обами у Twitter .

Це дуже дратує, коли воно з’являється в місцях, де важко налагодити або коли тестування нехтується. Тож краще уникати цього, якщо ви не повинні його використовувати.


Так, щойно витратили години на виявлення проблеми, викликаної тим, що файл кодується як UTF-8 замість UTF-8 без BOM. (Проблема з'явилася лише в IE7, так що мене повели на досить гусячу погоню. Я використовував "включити" Джанго.)
user984003

Майбутні читачі: Зауважте, що твіт-твіт, про який я згадував вище, не був суворо пов'язаний з BOM, але якби він був, то твіт буде одягнутись аналогічно, але на початку твіт.
Halil Özgür

12
@ user984003 Ні, проблема полягає в тому, що Microsoft ввів вас в оману. Те, що він називає UTF-8, це не UTF-8. Що називається UTF-8 без BOM, це те, що є насправді UTF-8.
tchrist

що додає "sic" у ваш "не каламбур призначений"
JoelFan

2
@JoelFan Я не можу згадати більше, але, мабуть, каламбур міг бути призначений, незважаючи на претензії автора :)
Halil Özgür

17

Питання: Що відрізняється між UTF-8 та UTF-8 без BOM? Який краще?

Ось кілька уривків із статті Вікіпедії про позначення порядку байтів (BOM), які, на мою думку, пропонують ґрунтовну відповідь на це питання.

Про значення BOM та UTF-8:

Стандарт Unicode дозволяє BOM в UTF-8 , але не вимагає і не рекомендує його використовувати. Порядок байтів не має значення в UTF-8, тому його єдине використання в UTF-8 - це сигналізувати на початку, що текстовий потік закодований в UTF-8.

Аргумент за те, що НЕ використовувати BOM:

Основна мотивація невикористання BOM - це зворотна сумісність із програмним забезпеченням, яке не обізнане з Unicode ... Ще одна мотивація невикористання BOM - це заохочення UTF-8 як кодування "за замовчуванням".

Аргумент ЗА використання BOM:

Аргумент для використання BOM полягає в тому, що без цього необхідний евристичний аналіз, щоб визначити, який символ кодує файл. Історично такий аналіз, щоб виділити різні 8-бітові кодування, є складним, схильним до помилок, а іноді і повільним. Для полегшення завдання доступна низка бібліотек, такі як Mozilla Universal Charset Detector та International Components for Unicode.

Програмісти помилково припускають, що виявити UTF-8 однаково важко (це не тому, що переважна більшість послідовностей байтів є недійсними UTF-8, тоді як кодування, які ці бібліотеки намагаються розрізнити, дозволяють усі можливі послідовності байтів). Тому не всі програми, що знають Unicode, проводять такий аналіз і замість цього покладаються на BOM.

Зокрема, компілятори та інтерпретатори Microsoft , а також багато програмного забезпечення в Microsoft Windows, таких як Блокнот, не будуть правильно читати текст UTF-8, якщо він не містить лише символів ASCII або він починається з BOM, і додасть BOM до початку при збереженні текст як UTF-8. Документи Google додадуть BOM, коли документ Microsoft Word завантажується у вигляді простого текстового файлу.

Що краще, З або БЕЗ :

IETF рекомендує , якщо протокол або (а) завжди використовує UTF-8, або (б) має якийсь - то інший спосіб , щоб вказати , що використовується кодування, то «слід заборонити використання U + FEFF в якості підпису.»

Мій висновок:

Використовуйте BOM лише в тому випадку, якщо сумісність із програмним додатком абсолютно необхідна.

Також зауважте, що хоча посилання на статтю Wikipedia вказує на те, що багато програм Microsoft покладаються на BOM для правильного виявлення UTF-8, це не стосується всіх програм Microsoft. Наприклад, як вказував @barlop , при використанні командного рядка Windows з UTF-8 команди такі, typeі moreне очікуйте, що BOM буде присутній. Якщо специфікація знаходиться присутній, вона може бути проблематичною, так і для інших застосувань.


chcpКоманда пропонує підтримку UTF-8 ( без BOM) через кодову сторінку 65001 .


5
Мені краще суворо БЕЗ БОМ . Я виявив , що .htaccessі gzip compressionв поєднанні з UTF-8 BOM видає помилку кодування Змінити для кодування в UTF-8 без BOM слідують до пропозиції , як пояснено тут вирішують проблеми
Chetabahana

1
"Ще одна мотивація не використовувати BOM - це заохочувати UTF-8 як кодування" за замовчуванням "." - Який настільки сильний та вагомий аргумент, що ви могли насправді зупинити відповідь там! ...; - Якщо тільки ви не маєте кращого уявлення про універсальне подання тексту, тобто. ;) (Я не знаю, скільки тобі років, скільки років тобі довелося страждати в епоху до UTF8 (коли мовознавці відчайдушно думали навіть про зміну своїх алфавітів), але я можу вам сказати, що кожну секунду ми наближаємось до позбавлення безлад усіх давніх однобайтових кодувань без метаданих, замість того, щоб "один" - це чиста радість.)
Sz.

Дивіться також цей коментар про те, як додавання BOM (або що-небудь ще!) До найпростіших із форматів текстових файлів, "звичайного тексту", означатиме запобігання саме найкращому універсальному формату кодування тексту від "простого" та "простого" (тобто "над головою")! ...
Sz.

BOM здебільшого проблематичний для Linux, оскільки багато утилітів насправді не підтримують Unicode для початку (наприклад, вони будуть щасливо скорочуватися посередині кодових точок). У більшості інших сучасних програмних середовищ використовуйте BOM, коли кодування не є однозначним (за допомогою специфікацій або метаданих).
Eric Grange

9

На це запитання вже є мільйон і один відповіді, і багато з них є досить хорошими, але я хотів спробувати уточнити, коли БОМ повинен чи не повинен використовуватися.

Як уже згадувалося, будь-яке використання UTF BOM (Byte Order Mark) для визначення того, чи є рядок UTF-8 чи ні, не є освіченою здогадкою. Якщо є відповідні метадані (наприклад charset="utf-8"), ви вже знаєте, що ви повинні використовувати, але в іншому випадку вам потрібно перевірити і зробити деякі припущення. Це включає перевірку, чи починається файл з рядка, починаючи з шістнадцяткового байтового коду, EF BB BF.

Якщо знайдений байт-код, відповідний BOM UTF-8, ймовірність достатньо висока, щоб припустити, що це UTF-8, і ви можете піти звідти. Однак, коли змушені зробити це здогадка, додаткова перевірка помилок під час читання все-таки буде хорошою ідеєю, якщо щось зіпсується. Ви повинні припустити, що BOM не є UTF-8 (тобто латинська-1 або ANSI), якщо вхід точно не повинен бути UTF-8 на основі його джерела. Якщо BOM відсутній, ви можете просто визначити, чи повинен це бути UTF-8, перевіривши кодування.

Чому BOM не рекомендується?

  1. Програмне забезпечення, яке не знає Unicode, або погано сумісне програмне забезпечення, може припустити, що це латиниця-1 або ANSI, і не зніме BOM з рядка, що, очевидно, може спричинити проблеми.
  2. Це насправді не потрібно (просто перевірте, чи вміст сумісний, і завжди використовуйте UTF-8 як резервну копію, коли не знайдено сумісного кодування)

Коли слід кодувати BOM?

Якщо ви не можете записати метадані будь-яким іншим способом (через тег шаблону або мета файлової системи), а програми, які використовуються як BOM, слід кодувати BOM. Особливо це стосується Windows, де звичайно вважається, що все, що не має BOM, використовує застарілу кодову сторінку. BOM повідомляє таким програмам, як Office, що так, текст у цьому файлі є Unicode; ось використано кодування.

Коли справа доходить до цього, єдині файли, з якими у мене колись виникають проблеми - це CSV. Залежно від програми, вона або повинна, або не повинна мати BOM. Наприклад, якщо ви використовуєте Excel 2007+ у Windows, він повинен бути закодований BOM, якщо ви хочете його відкрити плавно і не потрібно вдаватися до імпорту даних.


2
Останній розділ вашої відповіді на 100% правильний: Єдина причина використовувати BOM - це коли вам доведеться взаємодіяти з помилковим програмним забезпеченням, яке не використовує UTF-8 за замовчуванням для аналізу невідомих файлів.
rmunn

8

Слід зазначити, що для деяких файлів ви не повинні мати BOM навіть у Windows. Прикладами є SQL*plusабо VBScriptфайли. Якщо такі файли містять BOM, ви отримуєте помилку при спробі їх виконання.


8

UTF-8 з BOM допомагає лише в тому випадку, якщо файл насправді містить деякі символи, що не належать до ASCII. Якщо він включений, а таких немає, то, можливо, він може зламати старіші програми, які б інакше інтерпретували файл як звичайний ASCII. Ці програми, безумовно, не вдасться, коли вони натрапляють на не ASCII-символ, тому, на мій погляд, BOM слід додавати лише тоді, коли файл може і не повинен більше інтерпретуватися як звичайний ASCII.

Я хочу дати зрозуміти, що я волію взагалі не мати BOM. Додайте його, якщо якийсь старий сміття перерветься без нього, а заміна цього застарілого додатка неможлива.

Не варто сподіватися на те, що BOM для UTF-8.


7

Цитується внизу сторінки Вікіпедії на BOM: http://en.wikipedia.org/wiki/Byte-order_mark#cite_note-2

"Використання BOM не потрібно і не рекомендується для UTF-8, але може зустрічатися в контекстах, коли дані UTF-8 перетворюються з інших форм кодування, які використовують BOM або де BOM використовується як підпис UTF-8"


2
Чи є у вас приклад, коли програмне забезпечення приймає рішення про те, чи використовувати UTF-8 з / без BOM, виходячи з того, чи було в попередньому кодуванні, з якого він кодується, було BOM чи ні ?! Це здається абсурдним твердженням
барлоп

7

UTF-8 без BOM не має BOM, що не робить його кращим, ніж UTF-8 з BOM, за винятком випадків, коли споживачеві файлу потрібно знати (або виграє від того, щоб знати), чи файл у кодованому UTF-8 чи ні.

BOM зазвичай корисний для визначення витривалості кодування, що не потрібно для більшості випадків використання.

Крім того, BOM може бути непотрібним шумом / болем для тих споживачів, які не знають і не піклуються про це, і може призвести до плутанини користувачів.


2
"який не має користі для UTF-8, оскільки він 8-біт на гліф у будь-якому разі." Е ... ні, в UTF-8 тільки гліфи ASCII-7 є 8-бітними. Все, що перевищує це, буде 16, 24 або 32 біт.
Powerlord

3
"BOM зазвичай корисний для визначення витривалості кодування, яка не потрібна для більшості випадків використання." ... Ендіанічність просто не поширюється на UTF-8, незалежно від випадку використання
JoelFan

6

Я дивлюся на це з іншого погляду. Я думаю, що UTF-8 з BOM є кращим, оскільки він надає більше інформації про файл. Я використовую UTF-8 без BOM, тільки якщо зіткнувся з проблемами.

Я довго використовую кілька мов (навіть кирилицю ) на своїх сторінках, і коли файли зберігаються без BOM, і я повторно відкриваю їх для редагування за допомогою редактора (як також зазначав cherouvim ), деякі символи пошкоджуються.

Зауважте, що класичний блокнот Windows автоматично зберігає файли з BOM при спробі збереження новоствореного файлу з кодуванням UTF-8.

Я особисто зберігаю файли сценаріїв на стороні сервера (.asp, .ini, .aspx) з BOM та .html файлами без BOM .


4
Дякуємо за чудову пораду щодо класичного блокнота Windows. Я вже витратив деякий час на з’ясування точної речі. Моїм наслідком було завжди використовувати Notepad ++ замість Windows Класичний Notepad. :-)
barfuin

Ви краще використовуйте madedit. Це єдиний редактор, який у шестигранному режимі показує один символ, якщо ви вибрали послідовність байт utf-8 замість основи 1: 1 між байтом та символом. Шістнадцятковий редактор, який знає про файл UTF-8, повинен бути корисним, як це робить madedit!
яскравий

@brighty Я не думаю, що тобі потрібен один до одного заради BOM. це не має значення, не потрібно багато, щоб розпізнати utf-8 BOM є efbbbf або fffe (від fffe, якщо читати неправильно). Можна просто видалити ці байти. Непогано хоч мати карту для решти файлу, але також мати можливість також видалити байт за байтом
barlop

@barlop Чому ви хочете видалити BOM utf-8, якщо вміст файлу закодовано utf-8? BOM визнаний сучасними засобами перегляду тексту, керування текстом, а також текстовими редакторами. Перегляд послідовності utf-8 не має сенсу, оскільки n байтів призводять до одного символу. Звичайно, текстовий редактор або шестнадцятковий редактор повинен дозволяти видалити будь-який байт, але це може призвести до недійсних послідовностей utf-8.
яскравий

@brighty utf-8 with bom - це кодування, а utf-8 без bom - кодування. Запрошення cmd використовує utf8 без bom .. тому якщо у вас є файл utf8, ви запускаєте команду chcp 65001для підтримки utf8, це utf8 без bom. Якщо ви type myfileце зробите, він відображатиметься належним чином, лише якщо бомби немає. Якщо ви зробите echo aaa>a.aабо echo אאא>a.a виведете символи для файлу aa, і у вас є chcp 65001, він виведе без BOM.
барлоп

6

Коли ви хочете відобразити інформацію, закодовану в UTF-8, у вас можуть не виникнути проблеми. Задекларуйте, наприклад, документ HTML як UTF-8, і у вашому браузері буде все, що міститься в тілі документа.

Але це не так, коли ми маємо текстові, CSV та XML-файли або в Windows, або в Linux.

Наприклад, текстовий файл в Windows або Linux - одна з найпростіших речей, яку можна уявити, це (зазвичай) UTF-8.

Збережіть його як XML і оголосіть його як UTF-8:

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

Він не відобразиться правильно (його не буде прочитано) правильно, навіть якщо він оголошений як UTF-8.

У мене був ряд даних, що містять французькі літери, які потрібно було зберегти як XML для синдикації. Без створення файлу UTF-8 з самого початку (зміни параметрів в IDE та "Створення нового файлу") або додавання BOM на початку файлу

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

Мені не вдалося зберегти французькі літери у файлі XML.


1
FTM, в XML, я думаю, ви повинні зберігати файл як ASCII і використовувати об'єкти замість цього.
Алоїз Магдал

4
Я знаю, що це стара відповідь, але я просто хочу зазначити, що це неправильно. Текстові файли в Linux (не можуть говорити для інших Unixes) зазвичай / є / UTF-8.
Functino

6

Одна практична відмінність полягає в тому, що якщо ви напишете сценарій оболонки для Mac OS X і збережете його як звичайний UTF-8, ви отримаєте відповідь:

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

у відповідь на рядок shebang, вказуючи, яку оболонку ви бажаєте використовувати:

#!/bin/bash

Якщо ви збережете як UTF-8, без BOM (скажімо в BBEdit ) все буде добре.


8
Це тому, що Microsoft поміняв значення того, що говорить стандарт. У UTF-8 немає BOM: вони створили Microsoft UTF-8, який вставляє помилкову BOM перед потоком даних, а потім сказав вам, що ні, це насправді UTF-8. Це не так. Це просто розширення і розбещення.
tchrist

4

Як було сказано вище, UTF-8 з BOM може спричинити проблеми з програмним забезпеченням, яке не знає BOM (або сумісного). Я колись редагував HTML-файли, закодовані як UTF-8 + BOM, на базі Mozilla KompoZer , як клієнт вимагав, щоб програма WYSIWYG .

Незмінно макет може бути знищений при збереженні. Минуло певний час, щоб вирішити свій шлях. Потім ці файли добре працювали у Firefox, але знову показали CSS-химерність в Internet Explorer, що зруйнував макет. Після годинника, що поспілкувався із пов'язаними CSS-файлами, я виявив, що Internet Explorer не любить файл BOMfed HTML. Ніколи знову.

Також я щойно знайшов це у Вікіпедії:

Символи shebang представлені тими ж двома байтами в розширених кодуваннях ASCII, включаючи UTF-8, який зазвичай використовується для сценаріїв та інших текстових файлів у поточних системах, схожих на Unix. Однак файли UTF-8 можуть починатися з необов'язкової позначки порядку байти (BOM); якщо функція "exec" спеціально виявляє байти 0x23 0x21, то наявність BOM (0xEF 0xBB 0xBF) перед шебангом запобіжить виконанню інтерпретатора сценарію. Деякі органи влади рекомендують не використовувати позначку порядку байтів у сценаріях POSIX (схожий на Unix) [15] з цієї причини та для ширшої взаємодії та філософських проблем


4

Поширені запитання про марку порядку замовлення Unicode (BOM) містять стисну відповідь:

Питання: Як я маю поводитися з ВОМ?

Відповідь: Ось декілька вказівок, яких слід дотримуватися:

  1. Конкретний протокол (наприклад, конвенції Microsoft для файлів .txt) може вимагати використання BOM у певних потоках даних Unicode, таких як файли. Коли вам потрібно відповідати такому протоколу, використовуйте BOM.

  2. У деяких протоколах можливі необов'язкові BOM-файли у випадку без тегів тексту. У цих випадках

    • Якщо текстовий потік даних, як відомо, є звичайним текстом, але невідомого кодування, BOM може використовуватися як підпис. Якщо немає BOM, кодуванням може бути що завгодно.

    • Якщо текстовий потік даних, як відомо, являє собою звичайний текст Unicode (але не той, який є ендіан), то BOM може використовуватися як підпис. Якщо немає BOM, текст слід інтерпретувати як big-endian.

  3. Деякі протоколи, орієнтовані на байт, очікують символів ASCII на початку файлу. Якщо UTF-8 використовується з цими протоколами, слід уникати використання BOM як підпису форми кодування.

  4. Там, де відомий точний тип потоку даних (наприклад, Unicode big-endian або Unicode little-endian), BOM не слід використовувати. Зокрема, щоразу, коли потік даних оголошується UTF-16BE, UTF-16LE, UTF-32BE або UTF-32LE, BOM не повинен використовуватися.


1

З http://en.wikipedia.org/wiki/Byte-order_mark :

Марка порядку байтів (BOM) - символ Unicode, який використовується для сигналізації про ендіанси (порядок байтів) текстового файлу або потоку. Його кодова точка - U + FEFF. Використання BOM не є обов'язковим, і, якщо воно використовується, воно повинно з’являтися на початку текстового потоку. Крім конкретного використання в якості індикатора порядку байтів, символ BOM також може вказувати, в якому з декількох представлень Unicode текст закодований.

Завжди використання BOM у вашому файлі гарантує, що він завжди правильно відкривається в редакторі, який підтримує UTF-8 та BOM.

Моя реальна проблема з відсутністю BOM полягає в наступному. Припустимо, у нас є файл, який містить:

abc

Без BOM це відкривається як ANSI у більшості редакторів. Отож інший користувач цього файлу відкриває його та додає деякі рідні символи, наприклад:

abg-αβγ

На жаль, тепер файл все ще знаходиться в ANSI і вгадайте, що "αβγ" не займає 6 байтів, але 3. Це не UTF-8, і це спричиняє інші проблеми згодом у ланцюжку розробки.


9
Забезпечити появу помилкових байтів на початку програмного забезпечення, яке не знає BOM. Так.
Ромен

1
@Romain Muller: наприклад, PHP 5 видасть "неможливі" помилки при спробі надіслати заголовки після BOM.
Пісквор вийшов з будівлі

5
αβγ не є ascii, але може з'являтися у 8-бітових кодуваннях, кодованих на основі ассії. Використання BOM відключає прихильність utf-8, її сумісність з ascii (здатність працювати з реальними програмами, де застосовується чистий ascii).
ctrl-alt-delor

1
Це неправильна відповідь. Рядок з BOM перед ним - зовсім інше. Його там не передбачається, а просто все накручують.
tchrist

Без BOM це відкривається як ANSI у більшості редакторів. Я згоден абсолютно. Якщо це трапляється, вам пощастило, якщо ви маєте справу з правильною кодовою сторінкою, але насправді це лише здогадка, тому що сторінка коду не є частиною файлу. БОМ є.
яскравий

1

Ось мій досвід запитів на витягування Visual Studio, Sourcetree та Bitbucket , що спричиняє мені деякі проблеми:

Так виходить, що BOM з підписом буде містити символ червоної крапки у кожному файлі при перегляді запиту на витягнення (це може бути дуже прикро).

Введіть тут опис зображення

Якщо ви наведіть на нього курсор, він покаже такий персонаж, як "ufeff", але, виявляється, Sourcetree не відображає ці типи побічних знаків, тож, швидше за все, це виявиться у ваших запитах на виклик, що має бути нормальним, оскільки саме так Visual Studio 2017 кодує нові файли зараз, тому, можливо, Bitbucket повинен ігнорувати це або змусити його показувати іншим способом, більше інформації тут:

Червоний крапковий маркер BitBucket diff view


-4

UTF з BOM краще, якщо ви використовуєте UTF-8 у файлах HTML і якщо ви використовуєте сербську кирилицю, сербську латинську, німецьку, угорську або якусь екзотичну мову на одній сторінці.

Це моя думка (30 років обчислювальної та ІТ-індустрії).


1
Я вважаю це правдою також. Якщо ви використовуєте символи за межами першого набору 255 ASCII, і ви опускаєте BOM, браузери інтерпретують це як ISO-8859-1, і ви отримуєте похмурі символи. З огляду на відповіді вище, це, мабуть, у постачальників браузерів робить неправильно, коли вони не виявляють BOM. Але якщо ви не працюєте в Microsoft Edge / Mozilla / Webkit / Blink, у вас немає іншого вибору, крім роботи з дефектами цих додатків.
asontu

UTF що? UTF-8? UTF-16? Щось ще?
Пітер Мортенсен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.