Содержание


Кодируйте свои документы XML в UTF-8

(И дело здесь не в размере)

Comments

Развить навыки по этой теме

Этот материал — часть knowledge path для развития ваших навыков. Смотри Эта информация является частью пути обучения. См. XML и сжатие данных.

Сервис Sitemap компании Google не так давно вызвал небольшой переполох в сообществе XML, поскольку начал требовать, чтобы все карты сайтов публиковались исключительно в кодировке UTF-8 Unicode. Google не позволяет использовать даже альтернативные кодировки Unicode (например, UTF-16), не говоря уж об отличных от Unicode кодировках, таких как ISO-8859-1. С технической точки зрения это означает, что Google использует какой-то не соответствующий стандартам синтаксический анализатор XML, поскольку согласно Рекомендации XML «все XML-процессоры ДОЛЖНЫ принимать кодировки UTF-8 и UTF-16 Unicode 3.1». Однако является ли это действительно такой уж проблемой?

UTF-8 доступна для всех

Универсальность является первой и наиболее веской причиной выбора UTF-8. Эта кодировка способна работать практически с любой системой письма, используемой в наши дни. Некоторые пробелы остаются, но они становятся все более редкими и в настоящее время заполняются. Системы письма, которые остаются неохваченными, в большинстве своем также не были реализованы ни в каком другом наборе символов, а даже если и были реализованы, то не являются доступными в XML. В лучшем случае они реализуются фонт-хаками, надстроенными над однобайтными наборами символов, такими как Latin-1. Настоящая поддержка для таких редких систем письма в первую очередь появится в Unicode (причем вероятно, что исключительно в Unicode и нигде больше).

Однако это лишь один из аргументов в пользу Unicode. Почему следует выбирать UTF-8 вместо UTF-16 или других кодировок Unicode? Одной из самых очевидных причин является широкая поддержка инструментальных средств. C UTF-8 работает практически любой сколько-либо заметный редактор, который можно использовать с XML, включая JEdit, BBEdit, Eclipse, emacs и даже Блокнот Windows (Notepad). Никакая другая кодировка Unicode не может похвастаться столь широкой поддержкой инструментальных средств среди XML и не-XML утилит.

В некоторых случаях (например, в BBEdit и Eclipse) UTF-8 не является набором символов по умолчанию. Пора уже изменить установки по умолчанию – все инструментальные средства должны поставляться с выбором UTF-8 в качестве кодировки по умолчанию. Пока этого не случится, мы будем оставаться в «болоте» функционально несовместимых файлов, которые повреждаются при передаче через национальные границы, границы платформ и лингвистические границы. Однако пока все программы не будут иметь UTF-8 в качестве кодировки по умолчанию, установки по умолчанию можно легко изменить самостоятельно. Например, в Eclipse на панели «General/Editors» («Общие параметры/Редакторы»), показанной на рисунке 1, вы можете указать, что все файлы должны иметь кодировку UTF-8. Можно заметить, что Eclipse «хочет» иметь установку по умолчанию MacRoman; однако если позволить сделать это, ваши файлы не будут компилироваться при передаче программистам, работающим на компьютерах с операционной системой Microsoft® Windows® и любых компьютерах за пределами Америки и Западной Европы.

Рисунок 1. Изменение установленного по умолчанию набора символов в Eclipse
Изменение установленного по умолчанию набора символов в Eclipse
Изменение установленного по умолчанию набора символов в Eclipse

Разумеется, для того чтобы кодировка UTF-8 работала, разработчики, с которыми вы обмениваетесь файлами, также должны использовать UTF-8; но это не должно стать проблемой. В отличие от MacRoman, кодировка UTF-8 не ограничена всего несколькими системами письма и одной малораспространенной платформой. UTF-8 хорошо работает для всех и каждого. Совершенно иначе дело обстоит с MacRoman, Latin-1, SJIS и другими разнообразными традиционными национальными наборами символов.

UTF-8 также лучше работает с инструментальными средствами, которые не ожидают получения многобайтных данных. Другие форматы Unicode (например, UTF-16) обычно содержат многочисленные нулевые байты. Многие инструментальные средства интерпретируют эти байты как конец файла или какой-либо иной специальный разделитель, что приводит к неожиданным, непредвиденным и зачастую неприятным последствиям. Например, если данные UTF-16 «простодушно» загрузить в строку C, строка может оказаться обрезанной на втором байте первого символа ASCII. Файлы UTF-8 содержат только те нули, которые действительно должны быть нулями. Разумеется, не стоит выбирать для обработки документов XML подобные простоватые инструментальные средства. Однако документы часто завершают свой путь в таких необычных местах традиционных систем, где никто на самом деле не принимал во внимание и не понимал последствия «розлива нового вина в старые меха». В системах, не знакомых с Unicode и XML, вероятность появления проблем при использовании кодировки UTF-8 меньше, чем при работе с UTF-16 или другими кодировками Unicode.

Что говорят спецификации

XML являлся первым важным стандартом, который полностью поддерживает UTF-8, но это было только началом тенденции. Органы стандартизации все больше рекомендуют UTF-8. Например, URL-адреса, которые содержат отличные от ASCII символы, долгое время были трудноразрешимой проблемой в Интернете. Работающий на компьютере PC URL-адрес, который содержал отличные от ASCII символы, отказывался работать при загрузке на платформе Mac и наоборот. Эта проблема была решена лишь недавно, когда Консорциум World Wide Web (W3C) и Инженерная группа по развитию Интернета (IETF) договорились о том, что все URL-адреса будут кодироваться только в UTF-8 и ни в какой другой кодировке.

Обе организации (W3C и IETF) в последнее время стали более непреклонными в отношении выбора UTF-8 в общем и целом, а иногда и в качестве единственной кодировки. В документе The W3C Character Model for the World Wide Web 1.0: Fundamentals («Модель символов W3C для World Wide Web 1.0: основы») говорится: «Когда требуется какая-либо однозначная кодировка символов, ДОЛЖНА использоваться кодировка символов UTF-8, UTF-16 или UTF-32. Кодировка US-ASCII имеет восходящую совместимость с UTF-8 (строка US-ASCII также является строкой UTF-8, см. [RFC 3629]), поэтому UTF-8 может быть использована, если необходима совместимость с US-ASCII». На практике совместимость с US-ASCII является настолько полезной, что представляет собой практически обязательное требование. W3C мудро поясняет: «В других ситуациях, например для API, может быть более уместной кодировка UTF-16 или UTF-32. Возможные причины выбора одной из этих кодировок включают эффективность внутренней обработки и функциональную совместимость с другими процессами».

Я могу поверить в аргумент об эффективности внутренней обработки. Например, внутреннее представление строк языка Java™ основывается на UTF-16, что значительно ускоряет индексацию в строку. Однако код Java никогда не показывает свое внутреннее представление программам, с которыми он обменивается данными. Вместо этого для внешнего обмена данными используется java.io.Writer, при этом набор символов указывается явным образом. При осуществлении такого выбора настоятельно рекомендуется использовать UTF-8.

Требования IETF являются даже еще более явными. В документе The IETF Charset Policy [RFC 2277] («Политика IETF в отношении наборов символов») недвусмысленно указано:

Протоколы ДОЛЖНЫ быть способны использовать для всего текста набор символов UTF-8, который состоит из набора кодированных символов ISO 10646 в сочетании со схемой кодирования символов UTF-8, определенной в [10646] Приложении R (опубликованном в Поправке 2).

Протоколы МОГУТ дополнительно указывать на то, как использовать другие наборы символов или другие схемы кодирования символов для ISO 10646, например UTF-16, но невозможность использования UTF-8 является нарушением данной политики; такое нарушение потребовало бы применения какой-либо процедуры отклонения ([BCP9] раздел 9) с четким и веским обоснованием в документе спецификации протокола перед входом на путь следования стандартам или продвижением по этому пути.

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

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

Китайский, японский и корейский языки

Одним из распространенных ошибочных представлений является то, что UTF-8 будто бы представляет собой формат сжатия. Это в корне неверно. Символы в диапазоне ASCII занимают в UTF-8 только половину того пространства, которое они занимают в некоторых других кодировках Unicode, в частности в UTF-16. Однако некоторые символы требуют до 50 % больше пространства для кодирования в UTF-8 – особенно китайские, японские и корейские (CJK) иероглифы.

Но даже когда вы кодируете XML CJK в UTF-8, фактическое увеличение размера по сравнению с UTF-16, вероятно, не будет столь значительным. Например, документ XML на китайском языке содержит множество таких символов ASCII, как <, >, &, =, ", ', и пробел. Все эти символы занимают в UTF-8 меньше пространства, чем в UTF-16. Точная величина коэффициента сжатия или расширения варьируется от одного документа к другому, но в любом случае разница едва ли будет сильно бросаться в глаза.

Наконец, стоит отметить, что идеографическая письменность, подобная китайской и японской, обычно является «экономной» в отношении количества символов по сравнению с буквенной письменностью, например латиницей и кириллицей. Некоторое большое абсолютное количество этих символов требуют трех и более байтов на символ для полного представления указанных систем письма; это означает, что одни и те же слова и предложения могут выражаться с помощью меньшего числа символов, чем в таких языках, как английский и русский. Например, японская идеограмма для дерева – 木. (Это выглядит немного похоже на дерево). Данная идеограмма занимает в UTF-8 три байта, в то время как английское слово «tree» («дерево») состоит из четырех букв и занимает четыре байта. Японская идеограмма для рощи – æž— (два дерева рядом друг с другом). Она также занимает в UTF-8 три байта, в то время как английское слово «grove» («роща») состоит из пяти букв и занимает пять байтов. Японская идеограмма 森 (три дерева) по-прежнему занимает всего три байта. А эквивалентное английское слово «forest» («лес») занимает шесть.

Если же вас действительно интересует сжатие, сжимайте XML с помощью утилит zip или gzip. Сжатый UTF-8, вероятно, будет близок по размеру к сжатому UTF-16 независимо от первоначальной разницы в размерах. Изначально больший размер одного из документов будет скомпенсирован бóльшей избыточностью, устраняемой алгоритмом сжатия.

Надежность

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

Еще более важной характеристикой UTF-8 является отсутствие необходимости фиксации состояния. Каждый байт потока или последовательности UTF-8 является однозначным. В UTF-8 вы всегда знаете, где находитесь – т. е. по отдельному байту вы сразу можете определить, является ли он однобайтным символом, первым байтом двухбайтного символа, вторым байтом двухбайтного символа либо вторым, третьим или четвертым байтом трех- или четырехбайтного символа. (Это далеко не все возможности, но приведенная информация поможет вам получить общее представление). В UTF-16 вы не всегда знаете, представляет ли байт «0x41» букву «A». Иногда это так, а иногда – нет. Вам нужно в достаточной степени отслеживать состояние, чтобы понять, в каком месте потока находитесь. Если какой-либо отдельный байт теряется, то все последующие данные, начиная с этого места, повреждаются. В UTF-8 потерянные или искаженные байты обнаруживаются сразу не влекут за собой повреждение остальных данных.

Кодировка UTF-8 не является идеальной для всех без исключения применений. Приложения, которые требуют произвольного доступа к конкретным индексам в пределах документа, могут работать быстрее при использовании какой-либо кодировки с фиксированной шириной, например UCS2 или UTF-32. (UTF-16 – является кодировкой с переменной шириной, если принимать во внимание замещающие пары). Однако обработка XML не относится к таким приложениям. Спецификация XML фактически требует, чтобы синтаксические анализаторы начинали анализ с первого байта документа XML и продолжали анализ до конца, и все существующие синтаксические анализаторы работают именно так. Ускорение произвольного доступа никоим образом не помогло бы обработке XML; поэтому, хотя это и могло бы стать одной и веских причин использования какой-либо другой кодировки в базе данных или иной системе, это не имеет отношения к XML.

Заключение

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

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

Пришло время прекратить споры о наборах символов и кодировках – выберите UTF-8 и покончите с дискуссиями.


Ресурсы для скачивания


Похожие темы


Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=XML
ArticleID=946421
ArticleTitle=Кодируйте свои документы XML в UTF-8
publish-date=09252013