Следует ли считать устаревшими кодировки символов помимо UTF-8 (и, возможно, UTF-16 / UTF-32)?


31

Моя любимая мозоль смотрит на очень много программных проектов, которые имеют горы кода для поддержки набора символов. Не поймите меня неправильно, я за совместимость, и я рад, что текстовые редакторы позволяют открывать и сохранять файлы в нескольких наборах символов. Что меня раздражает, так это то, что распространение неуниверсальных кодировок символов называется «надлежащей поддержкой Юникода», а не «проблемой».

Например, позвольте мне выбрать PostgreSQL и его поддержку набора символов . PostgreSQL работает с двумя типами кодировок:

  • Кодировка клиента: используется для связи между клиентом и сервером.
  • Кодировка сервера: используется для внутреннего хранения текста в базе данных.

Я могу понять, почему поддержка большого количества клиентских кодировок - это хорошо. Это позволяет клиентам, которые не работают в UTF-8, обмениваться данными с PostgreSQL без необходимости выполнять преобразование. Чего я не понимаю: почему PostgreSQL поддерживает несколько серверных кодировок? Файлы базы данных (почти всегда) несовместимы от одной версии PostgreSQL к другой, поэтому совместимость с разными версиями здесь не проблема.

UTF-8 - это единственный стандартный ASCII-совместимый набор символов, который может кодировать все кодовые точки Unicode (если я ошибаюсь, дайте мне знать). Я нахожусь в лагере, что UTF-8 - лучший набор символов, но я готов мириться с другими универсальными наборами символов, такими как UTF-16 и UTF-32.

Я считаю, что все неуниверсальные наборы символов должны быть устаревшими. Есть ли веская причина, по которой они не должны?


4
@mario: оригинальное определение UTF-8 допускает до 6 байтов. Позже он был искусственно ограничен, чтобы покрывать только символы, которые мог поддерживать UTF-16.
Ден04

6
По крайней мере, PostgreSQL сознательно работает с несколькими кодировками символов. Отстойно иметь дело со случайным сочетанием UTF-8 и windows-1252, потому что кому-то просто все равно.
Ден04

5
@ dan04: Работа с русскими текстами раньше была проблемой, так как они использовали несколько кодировок, которые существенно различались и обычно просто взламывали вещи, используя разные шрифты (что часто ложь о кодировке, используемой в их метаданных). В общем, ужасный беспорядок. Я подозреваю, что они все очистили - возможно, переместившись в UTF-8 - потому что количество запросов на поддержку в этом направлении сократилось.
Донал Феллоуз

3
Теоретический диапазон Unicode составляет от 0 до 0x10ffff. Больше ничего. Это то, что говорит стандарт Unicode. UTF-8 обрабатывает все Unicode и всегда будет. Он не охватывает гипотетический диапазон кодировки, которая не является Unicode, но охватывает весь Unicode.
gnasher729

Ответы:


16

Поскольку вы упомянули PostgreSQL, я могу с некоторой степенью достоверности сказать, что основная причина, по которой кодировки, не относящиеся к UTF8, поддерживаются на таких деталях, заключается в том, что это нужно японцам. По-видимому, идентичное преобразование в обоих направлениях между Unicode и различными японскими «устаревшими» кодировками не всегда возможно, а в некоторых случаях таблицы преобразования даже различаются у разных поставщиков. Это действительно сбивает с толку, но это, очевидно, так. (Широкая поддержка набора символов также является одной из причин, почему PostgreSQL так популярен в Японии.)

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

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


Итак, из-за этих кодировок преобразование текста в UTF-8 и обратно в целом с потерями? Даже если обратное преобразование будет сделано немедленно (а не через 6 месяцев)?
Джои Адамс

Джои Адамс: Видимо так.
Питер Айзентраут

3
Google для «объединения Хань», чтобы увидеть, почему
Петр Викторин

7

Две очевидные причины: в зависимости от данных, которые вы храните, преобразование в другой формат может занять довольно много времени и дополнительного места. Если вы храните 400 мегабайт информации, удвоение требований к хранилищу не составляет большого труда - но если вы храните 400 терабайт, это начинает означать немного больше. Преобразование 400 терабайт данных из (скажем) Shift-JIS в UTF-x также может занять некоторое время.

Это становится особенно трудным, если у вас есть (например) гарантии безотказной работы, которые говорят, что база данных будет доступна для всех, но, скажем, 10 минут из любого данного года, и у вас есть база данных, которая обновляется несколько сотен раз в секунду. Имейте в виду, что в такой ситуации все еще возможно управлять крупными конверсиями, но это не то, что нужно предпринимать легко. В некоторых случаях это может легко занять годы планирования, чтобы подготовиться к такому преобразованию.

Если вы начинаете с базы данных, которая (например) поддерживает только ASCII, возможно , есть веская причина обсудить, имеет ли смысл добавить поддержку всех этих кодировок, но если вы уже поддерживаете их, мало что можно извлечь из отбрасывания. поддержка для них.

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

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


1
Shift-JIS не является самосинхронизирующимся, что делает поиск громоздким. Вы бы получили значительное упрощение, не поддерживая его.
Ден04

@ dan04: если у вас уже есть проверенные временем процедуры поиска / индексации для Shift-JIS, переключение на UTF-8 или даже UCS2, вероятно, улучшит производительность незначительно. Для новой базы данных вы можете выбрать лучшую, более удобную и регулярную кодировку, например UCS2 или UTF-16.
9000

@ dan04: если бы ты вообще мог не поддерживать его, ты бы выиграл совсем немного. Пока вы поддерживаете его, исходящий от / идущий к клиентам, вы будете застревать с большей частью его уродства ...
Джерри Коффин

5

Есть пара проблем с хранением только UTF-8 на сервере:

  1. Каков предел VARCHAR(20)столбца? Это 20 байтов или 20 «символов» (а в Unicode, что такое «символ», когда вы учитываете комбинирование символов, лигатур и т. Д.?). Хуже того, как насчет того, CHAR(20)где он фактически должен зарезервировать все возможное пространство: я полагаю, что в MySQL он резервирует в 4 раза больше байтов для столбца в кодировке UTF-8 (то есть 80 байтов для CHAR(20)) только для обработки наихудшего случая.
  2. Необходимо выполнить постоянные преобразования кодировки между кодировкой сервера и кодировкой вашего клиента. Можно утверждать, что вы также хотите прекратить поддержку нескольких клиентских кодировок, но если вы этого не сделаете, все строки необходимо преобразовывать все время. Если вы можете сопоставить кодировку вашего сервера и кодировку клиента, то преобразования не требуются.
  3. Как отмечали другие, UTF-8 достаточно эффективен для хранения английского текста, но он очень неэффективен для других языков - в частности, для восточноазиатских языков. Полагаю, вы могли бы разрешить использовать UTF-16 или UTF-8 в качестве костюма. Или сжать текст, но это делает индексацию и поиск неэффективными.

Сказав все это, я согласен с вами: унаследованные кодировки в большинстве случаев бессмысленны, и Unicode, как правило, является лучшей кодировкой для всех новых приложений. Если бы я сегодня писал сервер баз данных с нуля, я бы поддерживал только Unicode и вообще не поддерживал бы устаревшую кодировку.

Разница в том, что PostgreSQL и большинство других серверов баз данных, используемых сегодня, существовали еще до того, как Unicode был приемлемым вариантом. Таким образом, у них уже была поддержка унаследованных кодировок (конечно, они не были унаследованными тогда), и нет особого смысла вырывать весь этот код по идеологическим причинам.


10
"но это очень неэффективно для других языков - в частности, для восточноазиатских языков" Даже на практике? Рассмотрим эту страницу китайской Википедии . Несмотря на то, что в исходном коде страницы отображается очень много китайских символов, символы ASCII превосходят их почти 7: 1.
Джои Адамс

2
Если N в вашем столбце CHAR (N) является частью четко определенного формата идентификатора (например, VIN определен как ровно 17 символов), то он, вероятно, не требует объединения символов или лигатур. Если нет, то N - просто произвольный предел, который следует интерпретировать щедро, чтобы избежать усечения данных.
Ден04

5
@Joey Adams: это верно для HTML и XML, где сама разметка составляет большую часть текста (и именно поэтому я думаю, что UTF-8 - хороший выбор для Интернета), но в базе данных вы не часто сохраняете HTML. В конце концов, это только фактор двух (или менее) различий, что на самом деле не так уж много.
Дин Хардинг

5
Пункт № 2 в этом ответе не имеет значения: он применяется независимо от того, используется ли Юникод. Пункт № 3 абсолютно преувеличивает неэффективность и ее масштаб. В то же время этот ответ значительно недооценивает проблемы, вызванные устаревшими кодировками. Легко предположить, что проблема не такая уж большая, если все, что вы когда-либо использовали в своей жизни, это английский.
Тимви

2
@Dean: я не знал, что не было возможности комментировать ответ без публикации своего собственного.
Тимви

3

Неуниверсальные (и особенно однобайтовые) кодировки имеют свое место: в системах, которые:

  • Недостаточно памяти для хранения базы данных символов Unicode.
  • Иметь однобайтовый шрифт, жестко запрограммированный в ПЗУ.
  • Не иметь доступа к Интернету, чтобы предоставить источник файлов с различной кодировкой.

Это верно сегодня для некоторых типов встраиваемых устройств. Но на рабочем столе и в серверной комнате не-Unicode-кодировки должны быть уже давно устаревшими.


3
Раньше у меня были такие домашние компьютеры. Я избавился от большинства из них в начале 80-х.
Дэвид Торнли

2

UTF-8 - лучший для вас эгоцентрик 1 англоговорящий. Если бы вы были японцами, примерно 99% ваших персонажей заняли бы 3-4 байта вместо двух в UTF-16.

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

В противном случае, я ненавижу, когда у меня есть текстовые документы, которые не в UTF- что-то . Я часто стараюсь изо всех сил, если мне нужно иметь правильное кодирование. В моей книге не кодировки Unicode мертвы.

1. Не принимайте эгоцентрическую роль лично. Я хотел сделать красочную иллюстрацию, и я на самом деле не это имел в виду.


3
@ Матфея - 4x явно в 4 раза больше, чем x (для положительного x). Я не понимаю, насколько здесь важна асимптотическая запись. Я никогда не видел, чтобы жесткий диск рекламировался с асимптотической скоростью роста. Обычно размер остается неизменным на протяжении всего срока службы привода.
Steve314

3
Миллионы символов в любом случае не поместятся в Юникоде. Согласно статье в Википедии, в настоящее время существует около шестидесяти тысяч ханьских символов. Поскольку Unicode - это не просто китайский, это означает, что в UTF-16 изрядное количество китайских символов будет занимать четыре байта, то есть столько, сколько UTF-8 получает в настоящее время. Было бы интересно посмотреть статистику по длинам китайских текстов в UTF-8 и UTF-16.
Дэвид Торнли

6
@David:> 99% всей японской и китайской письменности используют символы, которые требуют только 2 байта в UTF-16 и 3 в UTF-8. Персонажи, которые требуют большего, очень редки и / или историчны.
Тимви

8
Имейте в виду, что японский и китайский обычно используют меньше символов в слове. Я работаю с приложением, которое имеет большие языковые файлы на английском, японском и китайском языках, все они закодированы в utf-8. Китайский файл на самом деле самый маленький, в то время как японский файл примерно на 15% больше английского оригинала.
Gort the Robot

3
Ерунда. Все, что занимает два байта в UTF-16, занимает не более 3 байтов в UTF-8. Все, что составляет четыре байта в UTF-8, составляет 4 байта в UTF-16. Здесь нет «миллионов» китайских иероглифов, и, очевидно, они не вписываются в 16-битные.
gnasher729

1

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

Примеры проблем с Unicide:

  • UTF8 - разумный взлом, но большинство программ на основе UTF16 не работает. Большинство приложений Windows, поддерживающих Unicode, используют UTF16, включая саму ОС. Наиболее распространенной проблемой является не поддержка больше, чем базовая плоскость, то есть многословные символы.

  • Объединение Хань - это безудержная катастрофа. Невозможно смешать японский / китайский / корейский текст в одном документе без дополнительных метаданных, и трудно определить, какой шрифт следует использовать.

  • Комбинационные символы - еще одна катастрофа. Более разумные схемы кодирования отображают один символ в один код, что делает обработку строк относительно разумной. Юникод не имеет. Unicode даже не согласован - ханьские символы в основном являются комбинациями, но не кодируются как таковые, как европейские комбинационные символы.

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

Из-за этих и многих других проблем многие неанглийские программы не могут использовать Unicode и используют локальные кодировки символов. Это особенно характерно для японского и китайского программного обеспечения.

В идеале Unicode должен быть устаревшим. Кодировка символов TRON является довольно хорошей заменой Юникоду и в значительной степени совместима с существующим программным обеспечением, которое не будет обновляться.


Ваше утверждение о том, что невозможно смешивать разные варианты символов (японский / корейский / китайский), кажется устаревшим с 15 лет, стандарт Unicode 3.2 в 2002 году. Поддержка Unicode Селекторы вариаций, кодовые точки, которые после кодовой точки хана явно указывают, какую форму должен отображаться. Также комбинаторные символы указываются как «объединение диакритических знаков» с базовыми символами (а) и специальными глифами (å), процесс их преобразования наоборот - «нормализация». Так что нет, Unicode не сломан принципиально.
Торстен С.

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

0

Может быть, для записи, но не для чтения.

Существует много существующего контента, который использует эти кодировки, и некоторые кодировки, такие как base64, никуда не денутся, потому что некоторые текстовые протоколы предписывают их как способы внедрения двоичных данных.

Настоящей проблемой является автоматическое обнаружение кодировок, что приводит к дырам в безопасности. Я не возражаю против того, чтобы некоторые неясные кодировки, такие как UTF-7, просто исчезли.

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


7
Base64 не является кодировкой символов.
Ден04

0

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

  • Если вы храните / переносите текст base64, вам нужен только ASCII, и вы даже можете использовать 7-битные кодированные протоколы, такие как электронная почта. Дополнительные издержки UTF-8 не нужны.
  • Несколько файлов и существующих данных построены на этих старых кодировках символов, поэтому важно иметь возможность их читать.

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


1
Могут ли downvoters сказать, почему они понизили?
Берин Лорич

3
Я не понизил голос, но весь смысл base64 заключается в передаче двоичных данных по текстовому каналу. Если бы вы могли выбрать, какую кодировку использовать на этом канале, вы бы вообще не использовали кодировку текста. Даже если ваш канал действительно ASCII, base 64 использует только 6 из 7 битов - это уже значительная нагрузка.
Steve314

Я надеюсь, что кто-то не просто прочитал пункты пули. Это были исключения из использования UTF. И вы ошибаетесь в отношении базы 64, используя только 6 из 8 байтов. Первый набор символов ASCII - это непечатные управляющие символы, что заставляет некоторые символы в base64 использовать 7 из 8 байтов. Он намеренно избегает старшего бита, потому что не гарантируется, что все эти символы присутствуют в каждой кодовой странице, в то время как символы от 0 до 127 есть.
Берин Лорич

2
@Berin - (1) нет, но то, что "я согласен" не так уж и много без маркеров, и (2) база 64 имеет 64 "цифры". 64 цифры - это 6 бит, потому что 2 ^ 6 == 64. То, как вы представляете это в 7-битном кодовом пространстве (или 8 битах, или даже 8 байтах, если необходимо), не зависит от того, сколько данных на самом деле там. Избегание непечатных символов и т. Д. Является причиной накладных расходов - это не означает, что накладных расходов не существует. Выберите канал, предназначенный для двоичных данных, и эти издержки отсутствуют.
Steve314

3
Помните, что base64 был изобретен для отправки двоичных данных по текстовому каналу. Известно, что он неэффективен (расширение 3: 4), но имеет дело с техническими ограничениями в некоторых вариантах транспорта. Унаследованными были бы электронная почта и форумы UseNet, но более современное приложение будет встраивать двоичные данные в XML. Иногда правильного канала не существует , и вам приходится работать с ограничениями существующих.
Берин Лорич
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.