В чем разница между UTF-8 и UTF-8 без спецификации?

818

Чем отличаются UTF-8 и UTF-8 без спецификации ? Что лучше?

просто
источник
77
UTF-8 может лучше автоматически распознаваться по содержимому, чем по спецификации. Метод прост: попробуйте прочитать файл (или строку) как UTF-8, и, если это удастся, предположите, что данные - UTF-8. В противном случае предположим, что это CP1252 (или какая-то другая 8-битная кодировка). Любое восьмибитовое кодирование не-UTF-8 почти наверняка будет содержать последовательности, которые не разрешены UTF-8. Чистый ASCII (7 бит) интерпретируется как UTF-8, но результат также верен.
Tronic
39
Сканирование больших файлов для содержимого UTF-8 занимает много времени. Спецификация делает этот процесс намного быстрее. На практике вам часто нужно делать и то, и другое. В настоящее время виновником является то, что по-прежнему большая часть текстового содержимого не является Unicode, и я все еще сталкиваюсь с инструментами, которые говорят, что они поддерживают Unicode (например, UTF-8), но испускают их содержимое с другой кодовой страницей.
Йерун Wiert Pluimers
10
@ Троник Я не думаю, что «лучше» подходит в этом случае. Это зависит от окружающей среды. Если вы уверены, что все файлы UTF-8 помечены спецификацией, то проверка « спецификации» - это «лучший» способ, поскольку он быстрее и надежнее.
mg30rg
32
UTF-8 не имеет спецификации. Когда вы помещаете кодовую точку U + FEFF в начало файла UTF-8, нужно быть особенно осторожным при работе с ним. Это всего лишь одна из тех ложных имен Microsoft, которые называются кодировкой «Unicode», когда такой вещи нет.
tchrist
7
«Современный мэйнфрейм (и AIX) поддерживает UTF-8 с прямым порядком байтов» UTF-8 не имеет конца ! нет необходимости перемешивать байты, чтобы расположить пары или группы по четыре в правильном «порядке» для конкретной системы! Для обнаружения последовательности байтов UTF-8 может быть полезно отметить, что первый байт многобайтовой последовательности «кодовая точка» (байты, которые НЕ являются «простыми» ASCII), имеет установленный бит MS и все от одного до трех последовательно младшие биты, за которыми следует бит сброса. Общее количество этих установленных битов на один байт меньше, чем в этой
кодовой точке,

Ответы:

773

Спецификация UTF-8 представляет собой последовательность байтов в начале текстового потока ( 0xEF, 0xBB, 0xBF), которая позволяет читателю более надежно угадывать файл как кодированный в UTF-8.

Обычно, спецификация используется для сигнализации о порядке байтов кодирования, но, поскольку порядок байтов не имеет отношения к UTF-8, эта спецификация не нужна.

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

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

... Использование спецификации не требуется и не рекомендуется для UTF-8, но может встречаться в случаях, когда данные UTF-8 преобразуются из других форм кодирования, в которых используется спецификация, или когда спецификация используется в качестве сигнатуры UTF-8. , См. Подраздел «Порядок следования байтов» в разделе 16.8, «Специальные» , для получения дополнительной информации.

Мартин Кот
источник
114
Возможно, это не рекомендуется, но из моего опыта в конвертации иврита спецификация иногда имеет решающее значение для распознавания UTF-8 в Excel и может иметь значение для Джибриша и иврита
Матанья
26
Это не может быть рекомендовано, но это удивило мой сценарий powershell при попытке вывести «"øå»
Marius
63
Независимо от того, что это не рекомендовано стандартом, это разрешено, и я очень предпочитаю иметь что-то, что действует как подпись UTF-8, а не как альтернативы предположения или предположения. Unicode-совместимое программное обеспечение должно / должно быть в состоянии справиться с его присутствием, поэтому я лично рекомендую его использовать.
Мартино
30
@ bames53: Да, в идеальном мире хранение кодировки текстовых файлов в качестве метаданных файловой системы было бы лучшим способом сохранить их. Но большинство из нас, живущих в реальном мире, не могут изменить файловую систему ОС, на которой запускаются наши программы, поэтому использование независимой от платформы сигнатуры спецификации стандарта Unicode кажется лучшей и наиболее практичной альтернативой IMHO.
Мартино
34
@martineau Буквально вчера я столкнулся с файлом с спецификацией UTF-8, которая не была UTF-8 (это была CP936). К сожалению, те, кто ответственен за огромное количество боли, вызванной спецификацией UTF-8, в значительной степени не замечают этого.
bames53
243

Другие отличные ответы уже ответили, что:

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

Но, в качестве дополнительной информации к этому, спецификация для UTF-8 может быть хорошим способом «понюхать», если строка была закодирована в UTF-8 ... Или это может быть допустимая строка в любой другой кодировке ...

Например, данные [EF BB BF 41 42 43] могут быть:

  • Законный ISO-8859-1 строка «ï» ¿ABC»
  • Законный UTF-8 строку "ABC"

Поэтому, хотя было бы здорово распознать кодировку содержимого файла, посмотрев на первые байты, вы не должны полагаться на это, как показано в примере выше.

Кодировки должны быть известны, а не предсказаны.

paercebal
источник
60
@ Олкотт: Вы правильно поняли. Строка [EF BB BF 41 42 43] - это просто набор байтов. Вам нужна внешняя информация, чтобы выбрать, как ее интерпретировать. Если вы считаете, что эти байты были закодированы с использованием ISO-8859-1, то строка «ï» ¿ABC ». Если вы считаете, что эти байты были закодированы с использованием UTF-8, то это «ABC». Если вы не знаете, то вы должны попытаться выяснить. Спецификация может быть подсказкой. Отсутствие недопустимого символа при декодировании как UTF-8 может быть другим ... В конце концов, если вы не можете каким-то образом запомнить / найти кодировку, массив байтов - это просто массив байтов.
paercebal
19
@paercebal Хотя «ï» ¿является допустимым латинским-1, очень маловероятно, что текстовый файл начинается с этой комбинации. То же самое верно для маркеров ucs2-le / be ÿþ и þÿ. Также вы никогда не сможете узнать.
user877329
16
@deceze Это, вероятно, неверно с лингвистической точки зрения: сначала ï (что нормально), затем кавычка без пробела между ними (не нормально). ¿Указывает на то, что это испанский, но на испанском не используется. Вывод: это не латиница-1 с уверенностью намного выше уверенности без нее.
user877329
20
@ Пользователь Конечно, это не обязательно имеет смысл. Но если ваша система полагается на догадки , то тут возникают неопределенности. Некоторые злоумышленники преднамеренно отправляют текст, начинающийся с этих 3 букв, и ваша система неожиданно полагает, что смотрит на UTF-8 с спецификацией, обрабатывает текст как UTF-8, где он должен использовать Latin-1, и происходит некоторое внедрение Unicode. Просто гипотетический пример, но, безусловно, возможно. Вы не можете судить о кодировке текста по его содержанию, точка.
deceze
40
«Кодировки должны быть известны, а не предсказаны». Сердце и душа проблемы. +1, сэр Другими словами: либо стандартизируйте ваш контент и скажите: «Мы всегда используем эту кодировку. Период. Запишите его таким образом. Прочитайте его таким образом», или разработайте расширенный формат, позволяющий хранить кодировку в виде метаданных. (Последнему, вероятно, тоже нужна некоторая «стандартная кодировка начальной загрузки». Как, например, говорить «Часть, которая сообщает вам о кодировке, всегда ASCII.»)
jpmc26
135

Существует как минимум три проблемы с размещением спецификации в кодированных файлах UTF-8.

  1. Файлы без текста больше не являются пустыми, поскольку они всегда содержат спецификацию.
  2. Файлы, содержащие текст, который находится в подмножестве ASCII UTF-8, уже не являются ASCII, поскольку спецификация не является ASCII, что приводит к поломке некоторых существующих инструментов, и пользователи могут не иметь возможности заменить такие устаревшие инструменты.
  3. Невозможно объединить несколько файлов вместе, потому что каждый файл теперь имеет спецификацию в начале.

И, как уже упоминали другие, недостаточно или необходимо иметь спецификацию, чтобы обнаружить, что что-то является UTF-8:

  • Этого недостаточно, поскольку произвольная последовательность байтов может начинаться с точной последовательности, составляющей спецификацию.
  • В этом нет необходимости, потому что вы можете просто прочитать байты, как если бы они были UTF-8; если это удастся, это, по определению, действительный UTF-8.
JP
источник
8
В отношении пункта 1 «Файлы, которые не содержат текста, больше не являются пустыми, поскольку они всегда содержат спецификацию», это (1) связывает уровень файловой системы ОС с интерпретируемым уровнем содержимого, плюс оно (2) неверно предполагает, что при использовании спецификации необходимо поместить Спецификация также в каждом другом пустом файле. Практическое решение (1) состоит в том, чтобы не делать (2). По сути, жалоба сводится к тому, что «возможно нецелесообразно поместить спецификацию в пустой файл, что препятствует наиболее простому обнаружению логически пустого файла (путем проверки размера файла)». Тем не менее, хорошее программное обеспечение должно быть в состоянии справиться с этим, поскольку у него есть цель.
ура и hth. - Альф
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. Вероятно, лучшее решение состоит в том, чтобы избавиться от этих плохих инструментов.
ура и hth. - Альф
8
Пункт 3, «Невозможно объединить несколько файлов вместе, потому что каждый файл теперь имеет спецификацию в начале», просто ошибочен. У меня нет проблем с объединением файлов UTF-8 с BOM, так что это вполне возможно. Я думаю, возможно, вы имели в виду, что Unix-земля catне даст вам чистого результата, результата, который имеет спецификацию только на старте. Если вы это имели в виду, то это потому, что catработает на уровне байтов, а не на уровне интерпретируемого содержимого, и cat, например, не может работать с фотографиями. Тем не менее это не приносит большого вреда. Это потому, что спецификация кодирует неразрывный пробел нулевой ширины.
ура и hth. - Альф
20
@ Cheersandhth.-Alf Этот ответ правильный. Вы просто указываете на ошибки Microsoft.
tchrist
9
@brighty: ситуация не улучшается, если добавить бомбу.
дедупликатор
84

Вот примеры использования спецификации, которые на самом деле вызывают реальные проблемы, и все же многие люди не знают об этом.

BOM ломает скрипты

Сценарии оболочки, сценарии Perl, сценарии Python, сценарии Ruby, сценарии Node.js или любой другой исполняемый файл, который должен запускаться интерпретатором, - все начинается со строки shebang, которая выглядит следующим образом:

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

Он сообщает системе, какой интерпретатор должен быть запущен при вызове такого скрипта. Если сценарий закодирован в UTF-8, может возникнуть соблазн включить вначале спецификацию. Но на самом деле "#!" персонажи не просто персонажи. На самом деле это магическое число , состоящее из двух символов ASCII. Если вы поместите что-то (например, спецификацию) перед этими символами, тогда файл будет выглядеть так, как будто он имеет другое магическое число, и это может привести к проблемам.

Смотрите Википедию, статья: Шебанг, раздел: Магическое число :

Символы shebang представлены теми же двумя байтами в расширенных кодировках ASCII, включая UTF-8, который обычно используется для сценариев и других текстовых файлов в современных Unix-подобных системах. Однако файлы UTF-8 могут начинаться с дополнительной метки порядка байтов (BOM); если функция «exec» определенно обнаруживает байты 0x23 и 0x21, то наличие спецификации (0xEF 0xBB 0xBF) перед shebang будет препятствовать выполнению интерпретатора сценария.Некоторые авторитеты рекомендуют не использовать метку порядка байтов в сценариях POSIX (Unix-like) [14] по этой причине и для более широкой функциональной совместимости и философских соображений. Кроме того, метка порядка байтов в UTF-8 не требуется, так как это кодирование не имеет проблем с порядком байтов; он служит только для идентификации кодировки как UTF-8. [выделение добавлено]

Спецификация запрещена в JSON

См. RFC 7159, раздел 8.1 :

Реализации НЕ ДОЛЖНЫ добавлять метку порядка байтов в начало текста JSON.

Спецификация избыточна в 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

Теперь, если файл начинается с спецификации, он будет выглядеть так:

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.

Другие форматы данных

Спецификация в JSON не нужна, является незаконной и нарушает работу программного обеспечения в соответствии с RFC. Это должен быть нобрейнер, чтобы просто не использовать его тогда, и тем не менее, всегда есть люди, которые настаивают на нарушении JSON, используя спецификации, комментарии, разные правила цитирования или разные типы данных. Конечно, любой может свободно использовать такие вещи, как спецификации или что-то еще, если вам это нужно - просто не называйте это JSON.

Для форматов данных, отличных от JSON, посмотрите, как они на самом деле выглядят. Если единственными кодировками являются UTF- * и первый символ должен быть символом ASCII ниже 128, то у вас уже есть вся информация, необходимая для определения как кодировки, так и порядкового номера ваших данных. Добавление спецификаций даже в качестве дополнительной функции сделает ее более сложной и подверженной ошибкам.

Другое использование спецификации

Что касается использования вне JSON или сценариев, я думаю, что здесь уже есть очень хорошие ответы. Я хотел добавить более подробную информацию конкретно о сценариях и сериализации, потому что это пример символов спецификации, вызывающих реальные проблемы.

RSP
источник
5
rfc7159, который заменяет rfc4627, фактически предполагает, что поддержка спецификации может быть не такой уж злой. По сути, отсутствие спецификации является просто неоднозначным препятствием, поэтому старые программы Windows и Unix, не поддерживающие Unicode, могут обрабатывать utf-8.
Эрик Грандж
2
Звучит так, как будто JSON нуждается в обновлении, чтобы поддерживать его, то же самое касается сценариев Perl, Python, Ruby, Node.js. То, что эти платформы решили не включать поддержку, не обязательно отменяет использование спецификации. Apple пытается убить Adobe уже несколько лет, а Adobe все еще рядом. Но поучительный пост.
htm11h
13
@EricGrange, вы, кажется, очень сильно поддерживаете BOM, но не понимаете, что это сделало бы повсеместно распространенный, универсально полезный формат «простого текста» с оптимальным минимумом и пережитком прошлого до UTF8! Добавление любого вида (внутриполосного) заголовка к потоку простого текста по определению налагает обязательный протокол на самые простые текстовые файлы, делая его никогда не самым «простым»! И ради чего? Для поддержки всех других , древних кодировок CP, которые также не имели подписей, так что вы можете ошибочно принять их за UTF-8? (Кстати, ASCII тоже UTF-8. Значит, спецификация для них тоже?;) Да ладно.)
Sz.
2
Этот ответ является причиной, почему я пришел к этому вопросу! Я создал свои скрипты bash в Windows и столкнулся с множеством проблем при публикации этих скриптов в Linux! То же самое с файлами Джейсона.
Тоно Нам
2
Хотел бы я проголосовать за этот ответ примерно пятьдесят раз. Я также хочу добавить, что на данный момент UTF-8 выиграл войну стандартов, и почти весь текст, создаваемый в Интернете, - это UTF-8. Некоторые из самых популярных языков программирования (например, C # и Java) используют UTF-16 для внутреннего использования, но когда программисты, использующие эти языки, пишут файлы в выходные потоки, они почти всегда кодируют их как UTF-8. Следовательно, больше не имеет смысла иметь спецификацию для маркировки файла UTF-8; UTF-8 должен быть по умолчанию, который вы используете при чтении, и пробовать другие кодировки только в случае сбоя декодирования UTF-8.
Рунн
51

Чем отличаются UTF-8 и UTF-8 без спецификации?

Краткий ответ: в UTF-8 спецификация закодирована как байты EF BB BF в начале файла.

Длинный ответ:

Первоначально предполагалось, что Unicode будет кодироваться в UTF-16 / UCS-2. Спецификация была разработана для этой формы кодирования. Когда у вас есть 2-байтовые единицы кода, необходимо указать, в каком порядке находятся эти два байта, и общее соглашение для этого заключается в том, чтобы включить символ U + FEFF в качестве «метки порядка байтов» в начале данных. Символ U + FFFE постоянно не назначен, поэтому его присутствие можно использовать для обнаружения неправильного порядка байтов.

UTF-8 имеет один и тот же порядок байтов независимо от порядкового номера платформы, поэтому знак порядка байтов не требуется. Однако это может произойти (как последовательность байтов EF BB FF) в данных, которые были преобразованы в UTF-8 из UTF-16, или как «подпись», чтобы указать, что данные являются UTF-8.

Что лучше?

Без. Как ответил Мартин Кот, стандарт Unicode не рекомендует его. Это вызывает проблемы с программным обеспечением, не поддерживающим спецификацию.

Лучший способ определить, является ли файл UTF-8, - выполнить проверку достоверности. UTF-8 имеет строгие правила относительно того, какие последовательности байтов действительны, поэтому вероятность ложного срабатывания незначительна. Если последовательность байтов выглядит как UTF-8, вероятно, так оно и есть.

dan04
источник
8
это также сделало бы недействительным действительный UTF-8 с одним ошибочным байтом, хотя: /
эндолит
8
-1 «Это вызывает проблемы с программным обеспечением, не поддерживающим BOM». Для меня это никогда не было проблемой, но, напротив, отсутствие BOM вызывает проблемы с программным обеспечением, поддерживающим BOM (в частности, Visual C ++). проблема. Так что это утверждение очень специфично для платформы , узкой точки зрения Unix, но вводится в заблуждение так, как будто оно применимо в целом. Что это не так.
ура и hth. - Альф
6
Нет, у UTF-8 нет спецификации. Этот ответ неверен. Смотрите стандарт Unicode.
tchrist
2
Вы даже можете думать, что у вас есть чистый ASCII-файл, когда вы просто смотрите на байты. Но это может быть и файл utf-16, в котором вам нужно смотреть на слова, а не на байты. Современное программное обеспечение должно знать о спецификациях. При чтении utf-8 может произойти сбой, если будут обнаружены недопустимые последовательности, кодовые точки, которые могут использовать меньшую последовательность, или кодовые точки, которые являются суррогатами. Для utf-16 чтение может быть неудачным, когда есть суррогаты-сироты.
Ярко
1
@ Альф, я не согласен с вашей интерпретацией позиции, не относящейся к спецификации, как « специфичной для платформы , узкой точки зрения Unix-земли». Для меня единственный способ, которым ограниченность могла быть связана с "Unix land", была бы, если бы MS и Visual C ++ предшествовали * NIX, чего они не делали. Тот факт , что MS (я предполагаю , сознательно) начал использовать BOM в UTF-8 , а не UTF-16 , подсказывает мне , что они способствовали нарушению sh, perl, g++и многим другим бесплатным и мощных инструментов. Хотите, чтобы все работало? Просто купите версии MS. MS создала проблему, специфичную для платформы, так же, как бедствие их диапазона \ x80- \ x95.
bballdave025
30

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

Если файл CSV сохранен без спецификации, Excel считает, что это ANSI, и выдает бессмысленную информацию. После добавления «EF BB BF» на передней панели (например, путем повторного сохранения его с помощью Блокнота с UTF-8; или Блокнота ++ с UTF-8 с спецификацией) Excel прекрасно открывает его.

В RFC 3629 рекомендуется добавлять символ BOM к текстовым файлам Unicode: «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 и позже могут быть добавлены не ASCII. Я только что столкнулся с такой проблемой: программное обеспечение, которое ожидает utf8, создает файл с некоторыми данными для редактирования пользователем. Если исходный файл содержит только ASCII, открывается в некоторых редакторах, а затем сохраняется, он заканчивается на латинице 1 и все ломается. Если я добавлю спецификацию, она будет обнаружена редактором как UTF8, и все работает.
Роберто Альсина
1
Я нашел несколько инструментов, связанных с программированием, которые требуют, чтобы спецификация правильно распознала файлы UTF-8. Visual Studio, SSMS, SoureTree ....
kjbartel
5
Где вы читаете рекомендации по использованию спецификации в этом RFC? Самое большее, есть сильная рекомендация не запрещать это при определенных обстоятельствах, когда это трудно сделать.
Дедупликатор
8
Excel считает, что это ANSI и показывает бред, тогда проблема в Excel.
Исаак
17

Спецификация имеет тенденцию бум (не каламбур (так)) где-то, где-то. И когда он гремит (например, не распознается браузерами, редакторами и т. Д.), Он отображается как странные символы в начале документа (например, файл HTML, ответ JSON , RSS и т. Д.) и вызывает такие неудобства, как недавняя проблема с кодировкой, возникшая во время разговора Обамы в Twitter .

Это очень раздражает, когда появляется в местах, которые трудно отладить, или когда пренебрегают тестированием. Так что лучше избегать этого, если только вы не должны его использовать.

Халил Озгюр
источник
Да, просто потратил часы на выявление проблемы, вызванной тем, что файл кодируется как UTF-8 вместо UTF-8 без спецификации. (Эта проблема обнаружилась только в IE7, что привело меня в погоню за гусей. Я использовал Django "include".)
user984003
Будущие читатели: обратите внимание, что проблема с твитами, о которой я упоминал выше, не была строго связана с спецификацией, но если бы это было так, то твит был бы искажен подобным образом, но в начале твита.
Халил Озгюр
12
@ user984003 Нет, проблема в том, что Microsoft ввела вас в заблуждение. То, что он называет UTF-8, не является UTF-8. То, что он называет UTF-8 без спецификации, это то, чем на самом деле является UTF-8.
tchrist
что «sic» добавляет к вашему «не каламбур»
JoelFan
2
@JoelFan Я не могу вспомнить больше, но я думаю, что каламбур, возможно, был предназначен, несмотря на утверждение автора :)
Halil Özgür
17

Вопрос: Чем отличаются UTF-8 и UTF-8 без спецификации? Что лучше?

Вот некоторые выдержки из статьи Википедии о метке порядка байтов (BOM) которая, как я считаю, дает солидный ответ на этот вопрос.

По смыслу спецификации и UTF-8:

Стандарт Unicode разрешает спецификацию в UTF-8 , но не требует и не рекомендует ее использование. Порядок байтов не имеет значения в UTF-8, поэтому его использование только в UTF-8 заключается в том, чтобы в начале сигнализировать о том, что текстовый поток кодируется в UTF-8.

Аргумент за НЕ использование спецификации:

Основной мотивацией для отказа от использования спецификации является обратная совместимость с программным обеспечением, не поддерживающим Unicode ... Другой мотивацией для отказа от использования спецификации является поощрение UTF-8 в качестве кодировки по умолчанию.

Аргумент ЗА использование спецификации:

Аргумент в пользу использования спецификации заключается в том, что без нее требуется эвристический анализ, чтобы определить, какую кодировку символов использует файл. Исторически такой анализ, чтобы различать различные 8-битные кодировки, сложен, подвержен ошибкам, а иногда и медленен. Для облегчения этой задачи доступно несколько библиотек, таких как Mozilla Universal Charset Detector и Международные компоненты для Unicode.

Программисты ошибочно полагают, что обнаружение UTF-8 одинаково сложно (это не потому, что подавляющее большинство байтовых последовательностей являются недействительными UTF-8, тогда как кодировки, которые эти библиотеки пытаются различить, разрешают все возможные байтовые последовательности). Поэтому не все программы, поддерживающие Unicode, выполняют такой анализ и вместо этого полагаются на спецификацию.

В частности, компиляторы и интерпретаторы Microsoft , а также многие программные продукты в Microsoft Windows, такие как «Блокнот», не будут правильно читать текст UTF-8, если в нем нет только символов ASCII или он начинается с спецификации, и добавит спецификацию в начало при сохранении. текст как UTF-8. Документы Google добавят спецификацию при загрузке документа Microsoft Word в виде простого текстового файла.

На что лучше, С или БЕЗ спецификации

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

Мой вывод:

Используйте только спецификацию если совместимость с программным приложением абсолютно необходима.

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


† Команда chcpпредлагает поддержку UTF-8 ( без спецификации) через кодовую страницу 65001 .

DavidRR
источник
5
Я бы лучше строгий БЕЗ спецификации . Я обнаружил, что .htaccessи gzip compressionв сочетании с UTF-8 BOM выдает ошибку кодирования. Замените кодировку в UTF-8 без BOM, следуйте предложению,
описанному
1
«Другой мотивацией для отказа от использования спецификации является поощрение UTF-8 в качестве кодировки по умолчанию». - Что является настолько сильным и обоснованным аргументом, что вы могли бы фактически остановить ответ там! ...; -o Если у вас нет лучшей идеи для универсального представления текста, то есть. ;) (Я не знаю, сколько вам лет, сколько лет вы должны были страдать в эпоху до UTF8 (когда лингвисты отчаянно думали даже изменить свой алфавит), но я могу вам сказать, что каждую секунду мы приближаемся к избавлению путаница всех древних однобайтовых кодировок без метаданных, вместо того, чтобы иметь «единое целое», является чистой радостью.)
Sz.
См. Также этот комментарий о том, как добавление спецификации (или чего-либо еще!) К простейшему из форматов текстового файла, «простому тексту», означало бы предотвращение того, чтобы самый лучший универсальный формат кодирования текста был «простым» и «простым» (т.е. "без накладных расходов")! ...
Sz.
BOM в основном проблематичен в Linux, потому что многие утилиты не поддерживают Unicode с самого начала (например, они будут счастливо усекаться в середине кодовых точек). Для большинства других современных программных сред используйте спецификацию всякий раз, когда кодировка не является однозначной (через спецификации или метаданные).
Эрик Грандж
9

На этот вопрос уже есть миллион ответов, и многие из них довольно хороши, но я хотел попытаться уточнить, когда спецификацию следует или не следует использовать.

Как уже упоминалось, любое использование спецификации UTF (метки порядка байтов) при определении того, является ли строка UTF-8 или нет, является догадкой. Если есть доступные метаданные (например,charset="utf-8" ), то вы уже знаете, что должны использовать, но в противном случае вам нужно будет проверить и сделать некоторые предположения. Это включает проверку, начинается ли файл с строки, начинается с шестнадцатеричного байтового кода, EF BB BF.

Если найден байт-код, соответствующий спецификации UTF-8, вероятность достаточно высока, чтобы предположить, что это UTF-8, и вы можете перейти оттуда. Однако, если сделать такое предположение, дополнительная проверка ошибок во время чтения все равно будет хорошей идеей на случай, если что-то искажается. Вы должны только предполагать, что спецификация не UTF-8 (т. Е. Латинская-1 или ANSI), если ввод определенно не должен быть UTF-8 на основе его источника. Однако, если спецификации нет, вы можете просто определить, должен ли это быть UTF-8, проверив соответствие кодировке.

Почему спецификация не рекомендуется?

  1. Не поддерживающее Юникод или плохо совместимое программное обеспечение может предполагать, что оно латинское-1 или ANSI, и не удаляет спецификацию из строки, что, очевидно, может вызвать проблемы.
  2. Это на самом деле не нужно (просто проверьте, соответствует ли содержимое, и всегда используйте UTF-8 в качестве запасного варианта, когда не удается найти совместимую кодировку)

Когда следует вы кодировать с помощью спецификации?

Если вы не можете записать метаданные каким-либо другим способом (с помощью тега charset или мета файловой системы) и программ, используемых как спецификации, вам следует кодировать с помощью спецификации. Это особенно верно в Windows, где обычно предполагается, что что-либо без спецификации использует устаревшую кодовую страницу. Спецификация сообщает таким программам, как Office, что да, текст в этом файле - Unicode; вот используемая кодировка

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

JPC-ае
источник
2
Последний раздел вашего ответа на 100% правильный: единственная причина для использования спецификации - это когда вам приходится взаимодействовать с ошибочным программным обеспечением, которое по умолчанию не использует UTF-8 для анализа неизвестных файлов.
Рунн
8

Следует отметить, что для некоторых файлов у вас не должно быть спецификации даже в Windows. Примеры есть SQL*plusили VBScriptфайлы. Если такие файлы содержат спецификацию, вы получаете сообщение об ошибке при попытке их выполнить.

Вернфрид Домшайт
источник
8

UTF-8 с спецификацией помогает только в том случае, если файл на самом деле содержит символы не ASCII. Если он включен и его нет, он, возможно, сломает старые приложения, которые иначе интерпретировали бы файл как простой ASCII. Эти приложения определенно потерпят неудачу, когда столкнутся с не ASCII-символом, поэтому, по моему мнению, спецификацию следует добавлять только тогда, когда файл может и не должен больше интерпретироваться как простой ASCII.

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

Не заставляйте ничего ожидать спецификации для UTF-8.

Джеймс Уэйкфилд
источник
7

Цитируется внизу страницы Википедии в спецификации: http://en.wikipedia.org/wiki/Byte-order_mark#cite_note-2

«Использование спецификации не требуется и не рекомендуется для UTF-8, но может встречаться в случаях, когда данные UTF-8 преобразуются из других форм кодирования, в которых используется спецификация, или когда спецификация используется в качестве сигнатуры UTF-8»

ПИБ
источник
2
Есть ли у вас пример, когда программное обеспечение принимает решение о том, использовать ли UTF-8 с / без спецификации, основываясь на том, была ли предыдущая кодировка, из которой оно кодируется, была спецификация или нет ?! Это кажется абсурдным претензии
barlop
7

UTF-8 без спецификации не имеет спецификации, что не делает ее лучше, чем UTF-8 с спецификацией, за исключением случаев, когда пользователь файла должен знать (или выиграл бы от знания), закодирован ли файл в кодировке UTF-8 или нет.

Спецификация обычно полезна для определения порядкового номера кодирования, что не требуется для большинства случаев использования.

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

Ромен
источник
2
«который бесполезен для UTF-8, так как он в любом случае равен 8 битам на глиф». Э-э ... нет, только символы ASCII-7 являются 8-битными в UTF-8. Все, что за этим будет, будет 16, 24 или 32 бита.
Powerlord
3
«Спецификация обычно полезна для определения порядкового номера кодирования, который не требуется для большинства случаев использования». ... порядковый номер просто не применяется к UTF-8, независимо от
варианта
6

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

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

Обратите внимание, что классический блокнот Windows автоматически сохраняет файлы с спецификацией при попытке сохранить вновь созданный файл с кодировкой UTF-8.

Я лично сохраняю файлы сценариев на стороне сервера (.asp, .ini, .aspx) с BOM и .html файлами без BOM .

user1358065
источник
4
Спасибо за отличный совет о Windows Classic Notepad. Я уже потратил некоторое время на выяснение того же. Моим следствием было всегда использовать Notepad ++ вместо классического Windows Notepad. :-)
barfuin
Вам лучше использовать Мадедит. Это единственный редактор, который - в шестнадцатеричном режиме - показывает один символ, если вы выберете последовательность байтов utf-8 вместо основы 1: 1 между байтом и символом. Шестнадцатеричный редактор, который знает о файле UTF-8, должен выглядеть как madedit!
Ярко
@brighty Я не думаю, что тебе нужно один на один ради спецификации. это не имеет значения, не нужно много, чтобы распознать, что спецификация utf-8 - это efbbbf или fffe (fffe, если прочитано неправильно). Можно просто удалить эти байты. Хотя неплохо иметь отображение для остальной части файла, но также иметь возможность удалять побайтово
barlop
@barlop Почему вы хотите удалить спецификацию utf-8, если содержимое файла имеет кодировку utf-8? Спецификация распознается современными программами просмотра текста, элементами управления текстом и текстовыми редакторами. Однозначное представление последовательности utf-8 не имеет смысла, поскольку n байтов приводят к одному символу. Конечно, текстовый редактор или hex-редактор должны позволять удалять любой байт, но это может привести к неверным последовательностям utf-8.
Яркий
@brighty utf-8 с 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, он будет выводиться без спецификации.
Бароп
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 и «Создать новый файл») или добавления спецификации в начале файла

$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, без спецификации (скажем, в BBEdit ) все будет хорошо.

Дэвид
источник
8
Это потому, что Microsoft поменяла смысл того, что говорится в стандарте. У UTF-8 нет спецификации: они создали Microsoft UTF-8, которая вставляет ложную спецификацию перед потоком данных, а затем сказала, что нет, на самом деле это UTF-8. Не то. Это просто расширяется и развращает.
tchrist
4

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

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

Кроме того, я только что нашел это в Википедии:

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

Марек Мёлинг
источник
4

Часто задаваемые вопросы по метке порядка байтов в Юникоде дают краткий ответ:

Q: Как я должен иметь дело с спецификациями?

A: Вот несколько рекомендаций, которым нужно следовать:

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

  2. Некоторые протоколы допускают использование дополнительных спецификаций в случае нетегированного текста. В этих случаях

    • Если известно, что поток текстовых данных представляет собой простой текст, но неизвестной кодировки, в качестве подписи может использоваться спецификация. Если спецификации нет, кодировка может быть любой.

    • Если известно, что поток текстовых данных представляет собой простой текст в Юникоде (но не с прямым порядком байтов), то в качестве подписи может использоваться спецификация. Если спецификация отсутствует, текст следует интерпретировать как big-endian.

  3. Некоторые байтовые протоколы ожидают символы ASCII в начале файла. Если UTF-8 используется с этими протоколами, следует избегать использования спецификации в качестве подписи формы кодирования.

  4. Если известен точный тип потока данных (например, Unicode с прямым порядком байтов или Unicode с прямым порядком байтов), спецификация не должна использоваться. В частности, всякий раз, когда поток данных объявляется UTF-16BE, UTF-16LE, UTF-32BE или UTF-32LE, BOM не должен использоваться.

Вернфрид Домшайт
источник
1

От http://en.wikipedia.org/wiki/Byte-order_mark :

Метка порядка байтов (BOM) - это символ Unicode, используемый для обозначения порядка байтов (порядка байтов) текстового файла или потока. Кодовая точка U + FEFF. Использование спецификации является необязательным и, если используется, должно отображаться в начале текстового потока. Помимо его конкретного использования в качестве индикатора порядка байтов, символ спецификации может также указывать, в каком из нескольких представлений Unicode кодируется текст.

Всегда использование спецификации в вашем файле гарантирует, что она всегда правильно открывается в редакторе, который поддерживает UTF-8 и BOM.

Моя настоящая проблема с отсутствием спецификации заключается в следующем. Предположим, у нас есть файл, который содержит:

abc

Без спецификации это открывается как ANSI в большинстве редакторов. Таким образом, другой пользователь этого файла открывает его и добавляет некоторые нативные символы, например:

abg-αβγ

Упс ... Теперь файл все еще находится в ANSI и угадайте, что, "αβγ" не занимает 6 байтов, но 3. Это не UTF-8, и это вызывает другие проблемы позже в цепочке разработки.

cherouvim
источник
9
Убедитесь, что в начале программного обеспечения, не поддерживающего спецификацию, появляются ложные байты. Ура.
Ромен
1
@Romain Muller: например, PHP 5 будет выдавать «невозможные» ошибки при попытке отправить заголовки после спецификации.
Писквор покинул здание
5
αβγ не является ascii, но может появляться в 8-битных кодировках, основанных на ascii. Использование BOM отключает бенафит utf-8, его совместимость с ascii (возможность работать с устаревшими приложениями, где используется чистый ascii).
Ctrl-Alt-Delor
1
Это неправильный ответ. Строка с спецификацией перед ней - это совсем другое. Это не должно быть там и просто все испортило.
tchrist
Без спецификации это открывается как ANSI в большинстве редакторов. Я согласен абсолютно. Если это происходит, вам повезло, если вы имеете дело с правильной кодовой страницей, но на самом деле это всего лишь предположение, потому что кодовая страница не является частью файла. Спецификация есть.
Яркий
1

Вот мой опыт работы с Visual Studio, Sourcetree запросами извлечения и Bitbucket, который вызывает у меня некоторые проблемы:

Таким образом, оказывается, что спецификация с подписью будет включать символ красной точки в каждом файле при просмотре запроса на извлечение (это может быть довольно раздражающим).

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

Если вы наведите на него курсор, он покажет символ, подобный «ufeff», но оказывается, что Sourcetree не показывает эти типы байт-меток, поэтому он, скорее всего, закончится вашими запросами на получение, что должно быть в порядке, поскольку Visual Studio 2017 теперь кодирует новые файлы, поэтому, возможно, Bitbucket должен проигнорировать это или заставить его показывать по-другому, больше информации здесь:

Красная точка маркера BitBucket diff view

Лео
источник
-4

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

Это мое мнение (30 лет компьютерной и IT индустрии).

user2173444
источник
1
Я считаю, что это тоже правда. Если вы используете символы за пределами первого набора 255 ASCII и опускаете спецификацию, браузеры интерпретируют ее как ISO-8859-1, и вы получаете искаженные символы. Учитывая ответы выше, очевидно, что производители браузеров делают неправильные вещи, когда они не обнаруживают спецификацию. Но если вы не работаете в Microsoft Edge / Mozilla / Webkit / Blink, у вас нет выбора, кроме как работать с дефектами, которые имеют эти приложения.
Asontu
UTF что? UTF-8? UTF-16? Что-то другое?
Питер Мортенсен