UTF-8 или UTF-16 или UTF-32 или UCS-2

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

Но с некоторым поиском я получил эту статью

http://msdn.microsoft.com/en-us/library/bb330962%28SQL.90%29.aspx

Так что я теперь запутался, что использовать сейчас UTF-8 / UTF-16 / UTF-32 / UCS-2

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

PS: я использую Asp.net и C# и SqlServer 2005

заранее спасибо

6 ответов

Решение

Это не проблема, потому что вы говорите:

Я использую Asp.net и C# и SqlServer 2005

SqlServer использует UTF-16 в некоторых местах (ntext, nvarchar, nchar) и UTF-8 в нескольких XML-ориентированных местах, без каких-либо странностей.

C# использует UTF-16 во всех своих строках, с инструментами для кодирования, когда дело доходит до работы с потоками и файлами, которые приводят нас к...

ASP.NET по умолчанию использует UTF-8, и трудно представить себе время, когда это не удачный выбор (даже для азиатских языков текстовая краткость таких языков сочетается с тем фактом, что названия и символы имеют особое значение в HTML, CSS, javascript, большинстве приложений XML и других потоках, которые вы будете отправлять, находятся в диапазоне от U+0000 до U+007F, что делает преимущество UTF-16 над UTF-8 в этом диапазоне менее значительным, чем с обычным текстом Азиатские языки).

Разговор между UTF-16 SqlServer и C# и UTF-8, который ASP.NET делает при чтении и записи, сделан для вас с настройками по умолчанию, но так как это один бит, который вы можете легко изменить, мой ответ поэтому будет использовать UTF-8. На самом деле вы будете использовать смесь -8 и -16, но вы не заметите большую часть времени (заметили ли вы, что уже делали это).

SQL Server несколько менее простителен, хотя бы потому, что во многих устаревших примерах текст, ожидаемый для использования человеком, помещается в поля varchar, text или char. Используйте их исключительно для кодов (например, все коды стран ISO находятся в диапазоне char(2), поэтому nchar(2) будет просто тратить пространство), и только nvarchar, ntext и nchar для вещей, которые люди, а не машины будут читать и писать.

Так что я теперь запутался, что использовать сейчас UTF-8 / UTF-16 / UTF-32 / UCS-2

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

UCS-2 устарел: он больше не может представлять каждый символ Unicode. UTF-8, UTF-16 и UTF-32 могут все. Но почему есть три разных способа кодирования одних и тех же символов?

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

  1. Эти строки состоят из 8-битных кодовых единиц.
  2. Этот 1 символ = 1 единица кода.

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

Сохранение предположения № 1 и исключение предположения № 2 дает вам кодирование переменной ширины(или многобайтовости). На сегодняшний день наиболее популярным кодированием переменной ширины является UTF-8.

Отбрасывание предположения № 1 и сохранение предположения № 2 дает вам кодировку широких символов. Unicode и UCS-2 были изначально разработаны для использования 16-битного кодирования с фиксированной шириной, что позволило бы получить 65 536 символов. Первые пользователи Unicode, такие как Sun (для Java) и Microsoft (для NT), использовали UCS-2.

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

Но Sun и Microsoft написали огромные API, основанные на 16-битных символах, и не были в восторге от переписывания их для 32-битных. К счастью, по-прежнему существовал блок из 2048 неназначенных символов из исходной 65,536-символьной "Базовой многоязычной плоскости", которую можно было назначить в качестве "суррогатов" для использования в парах для представления дополнительных символов: формы кодирования UTF-16. К сожалению, UTF-16 не соответствует ни одному из двух исходных предположений: он не 8-битный и не переменной ширины.

В итоге:

Используйте UTF-8, когда важно предположение о 8-битных единицах кода.

Это относится к:

  • Имена файлов и связанные вызовы ОС в Unix-системах, в которых есть давняя традиция разрешать кодирование с переменной шириной, но не могут принять '\x00 байты в строках и, следовательно, не могут использовать UTF-16 или UTF-32. Фактически, UTF-8 был изначально разработан для ОС на основе Unix (Plan 9).
  • Протоколы связи рассчитаны на потоки октетов.
  • Все, что требует двоичной совместимости с US-ASCII, но не дает специальной обработки значениям байта выше 127.

Используйте UTF-32, когда важно предположение о кодировании с фиксированной шириной.

Это полезно, когда вы заботитесь о свойствах символов в отличие от их кодировки, таких как эквиваленты Unicode для ctypes.h функции как isalpha, isdigit, toupper, так далее.

Используйте UTF-16, когда ни одно из предположений не так важно, но ваша платформа использовала UCS-2.

Вы пишете для Windows или для платформы.NET, разработанной для этого? Для Java? Тогда UTF-16 - ваш тип строки по умолчанию; может также использовать это.

Поскольку вы используете C#, все ваши строки будут закодированы в UTF-16. ASP.NET будет кодировать фактические HTML-страницы в UTF-8, но это делается негласно, и вам не нужно об этом заботиться.

Размерные соображения

Три формы кодирования UTF требуют разных объемов памяти для представления символа:

  • Символы от U+0000 до U+007F (ASCII) требуют 1 байт в UTF-8, 2 байта в UTF-16 или 4 байта в UTF-32.
  • Символы от U+0080 до U+07FF (символы IPA, греческий, кириллица, армянский, иврит, арабский, сирийский, таанский, NKo) требуют 2 байта в UTF-8, 2 байта в UTF-16 или 4 байта в UTF-32,
  • Символы от U+0800 до U+FFFF (остальная часть BMP, в основном для азиатских языков) требуют 3 байта в UTF-8, 2 байта в UTF-16 или 4 байта в UTF-32.
  • Символы от U+10000 до U+10FFFF требуют 4 байта во всех трех формах кодирования.

Таким образом, если вы хотите сэкономить место, используйте UTF-8, если ваши символы в основном ASCII, или UTF-16, если ваши символы в основном азиатские.

Прежде всего, забудьте о UCS-2: он устарел. Он содержит только подмножество символов Unicode. Забудьте и о UTF-32: он очень большой и очень избыточный. Это не полезно для передачи данных.

На веб-страницах наиболее экономичным является UTF-8, если большинство языков, с которыми вы работаете, похожи на западные (латинский, кириллица, греческий и т. Д.). Но если пропускная способность и время загрузки не являются проблемой, вы также можете использовать UTF-16. Просто убедитесь, что вы всегда знаете, в каком формате находятся данные, когда обрабатываете byte[], И не пытайтесь конвертировать в устаревшие 8-битные наборы символов, такие как ISO-8859 или Windows-1252, потому что в этом случае вы потеряете данные.

В коде C# ваш string объекты будут внутри UTF-16, и с этим ничего не поделаешь. Так что ваши обычные строковые операции (например, Substring()) не зависит от выбранного вами формата вывода. Можно утверждать, что это повышает производительность при кодировании в формате UTF-16, но оно того не стоит, если вы собираетесь передавать его через Интернет, где стоимость передачи большего UTF-16 превышает крошечный выигрыш при обработке.

В SQL Server вы должны использовать nvarchar(...),

UTF-8 или UTF-16 - хороший выбор. Они оба дают вам доступ ко всему диапазону кодовых точек Unicode без использования 4 байтов для каждого символа.

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

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

Краткое примечание: в принципе все может быть представлено в наборе символов Unicode. UTF-8 - это всего лишь одна кодировка, которая способна представлять все символы в этом наборе.

UCS-2 больше не подходит для использования. Он не может содержать символы за пределами U+FFFF.

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

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

Увы, я думаю, что проблема в том (как он заявляет в начале), что у него есть SQL Server 2005, который, если я не ошибаюсь, все еще использует UCS2 в качестве кодировки для N-типов данных (NVARCHAR и со)

Возможно, ему придется смириться с ограничением, которое приносит или обновить до более новой версии SQL Server. Как правило, то, что вы увидите, если начнете создавать дамп UTF-16, то есть стандартный юникод, используемый в.NET, так это то, что некоторые символы будут потеряны и заменены на? отметки в таблицах базы данных.

Другие вопросы по тегам