Сколько байтов занимает один символ Unicode?


239

Я немного запутался в кодировках. Насколько я знаю, старые символы ASCII занимали один байт на символ. Сколько байтов требуется для символа Юникода?

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

А что означают UTF-7, UTF-6, UTF-16 и т. Д.? Это разные версии Unicode?

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



15
Простите, простого ответа нет. Я нахожу все это немного беспорядочным. Unicode был объявлен как использующий два байта и способный представлять все символы, но оказывается, что двух байтов было недостаточно.
Джонатан Вуд

12
«Простой ответ»: символ Юникода занимает 1-4 байта. Юникод охватывает много языков, но не все. В прошлый раз, когда я посмотрел, например, Klingon не был официальным набором символов Unicode.
Питер Г.

9
Клингон не является частью самого стандарта Unicode, нет. Вместо этого используется личная зона использования Uniode (U + F8D0 - U + F8FF).
Реми Лебо

1
Спаситель вопрос - спасибо. Моя ситуация заключается в хранении данных через совместимые с SCORM 1.2 LMS ... стандарт для SCORM 1.2 'cmi.suspend_data' составляет 4096 байт данных, которые, как предполагал предыдущий разработчик, означали, что мы можем хранить 4096 символов. О человек, он был неправ - я только что обнаружил, почему наши закладки не работают на длинных курсах. Итак, теперь я знаю, что поскольку мы используем UTF-8, для каждого символа требуется 4 байта, что дает нам 1024 символа.
Данджа

Ответы:


147

Вы не увидите простого ответа, потому что его нет.

Во-первых, Unicode не содержит «каждого символа из каждого языка», хотя, безусловно, пытается.

Юникод сам по себе является отображением, он определяет кодовые точки, а кодовая точка - это число, связанное обычно с символом. Обычно я говорю, потому что есть такие понятия, как объединение персонажей. Вы можете быть знакомы с такими вещами, как акценты или умлауты. Они могут использоваться с другим символом, таким как aили, uчтобы создать новый логический символ. Следовательно, символ может состоять из 1 или более кодовых точек.

Чтобы быть полезным в вычислительных системах, нам нужно выбрать представление для этой информации. Это различные кодировки Unicode, такие как utf-8, utf-16le, utf-32 и т. Д. Они отличаются в основном размером их кодовых блоков. UTF-32 - простейшая кодировка, она имеет кодовый блок 32 бита, что означает, что отдельная кодовая точка удобно вписывается в кодовый блок. В других кодировках будут ситуации, когда для кодовой точки потребуется несколько кодовых единиц или эта конкретная кодовая точка вообще не может быть представлена ​​в кодировке (это проблема, например, для UCS-2).

Из-за гибкости объединения символов, даже в данной кодировке число байтов на символ может варьироваться в зависимости от символа и формы нормализации. Это протокол для работы с символами, которые имеют более одного представления (можно сказать, "an 'a' with an accent"что это 2 кодовые точки, одна из которых представляет собой объединяющий символ или "accented 'a'"одна кодовая точка).


1
ХОРОШО. Тогда сколько байтов занимает один данный символ, представленный в одной данной кодовой точке? Например, неразрывный пробел.
Николас Барбулеско

Комбинированные символы превращают жизнь программиста в ад, когда дело доходит до написания strlen (), substr () и других функций манипулирования строками в массивах UTF8. Такая работа никогда не будет завершена и всегда глючит.
Нулик

Я написал демонстрацию, в которой показаны файлы в кодировке Windows-1252, UTF8 и UTF8-BOM, интерпретируемые для каждой кодировки, и сравнил равенство результатов: github.com/vladyrn/encodings_demo
Влад

195

Как ни странно, никто не указал, как рассчитать, сколько байтов занимает один символ Unicode. Вот правило для строк в кодировке UTF-8:

Binary    Hex          Comments
0xxxxxxx  0x00..0x7F   Only byte of a 1-byte character encoding
10xxxxxx  0x80..0xBF   Continuation byte: one of 1-3 bytes following the first
110xxxxx  0xC0..0xDF   First byte of a 2-byte character encoding
1110xxxx  0xE0..0xEF   First byte of a 3-byte character encoding
11110xxx  0xF0..0xF7   First byte of a 4-byte character encoding

Итак, быстрый ответ: он занимает от 1 до 4 байтов, в зависимости от первого, который будет указывать, сколько байтов он займет.


8
Я считаю, что максимальное значение Hex для 4-байтового символа составляет 0xF7 (не 0xF4).
DJPJ

Спасибо вам большое! Я просто управлял + просматривал стандарт IETF и ничего не нашел в кодировании, а в статье, которую я читал, не было достаточно подробных сведений о том, сколько битов используется для представления числа конечного кода. очков за «характер».
MarcusJ

1
Теперь это на второй странице моего шпаргалки «Введение для новых членов команды» вместе с первыми двумя веселыми комментариями
Си Макшарфэйк

1
0xF4 был не ошибкой, а разъяснением. Кодовые точки Unicode находятся в диапазоне 0-0x10ffff, поэтому последняя кодовая точка кодируется как F4 8F BF BF.
Фредиано

38

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

Насколько я знаю, старые символы ASCII занимали один байт на символ.

Правильно. На самом деле, поскольку ASCII является 7-битной кодировкой, он поддерживает 128 кодов (95 из которых могут быть напечатаны), поэтому он использует только половину байта (если это имеет смысл).

Сколько байтов требуется для символа Юникода?

Юникод просто отображает символы в кодовые точки. Это не определяет, как их кодировать. Текстовый файл не содержит символов Unicode, но байты / октеты, которые могут представлять символы Unicode.

Я предполагаю, что один символ Unicode может содержать все возможные символы из любого языка - я прав?

Но почти Так что в основном да. Но все же нет.

Так сколько байт нужно для каждого символа?

То же, что ваш второй вопрос.

А что означают UTF-7, UTF-6, UTF-16 и т. Д.? Это какие-то версии Unicode?

Нет, это кодировки. Они определяют, как байты / октеты должны представлять символы Unicode.

Пара примеров. Если некоторые из них не могут быть отображены в вашем браузере (возможно, потому что шрифт не поддерживает их), перейдите к http://codepoints.net/U+1F6AA(замените 1F6AAкод в шестнадцатеричном коде), чтобы увидеть изображение.

    • U + 0061 ЛАТИНСКОЕ МАЛЕНЬКОЕ ПИСЬМО А: a
      • № 97
      • UTF-8: 61
      • UTF-16: 00 61
    • U + 00A9 АВТОРСКИЙ ЗНАК: ©
      • № 169
      • UTF-8: C2 A9
      • UTF-16: 00 A9
    • U + 00AE ЗАРЕГИСТРИРОВАННЫЙ ЗНАК: ®
      • № 174
      • UTF-8: C2 AE
      • UTF-16: 00 AE
    • U + 1337 ЭТИОПИЧЕСКИЕ СЛОЖНЫЕ PHWA:
      • № 4919
      • UTF-8: E1 8C B7
      • UTF-16: 13 37
    • U + 2014 EM DASH:
      • № 8212
      • UTF-8: E2 80 94
      • UTF-16: 20 14
    • ЗНАК U + 2030 НА МИЛЛИОН:
      • № 8240
      • UTF-8: E2 80 B0
      • UTF-16: 30 30
    • ЕВРО ЗНАК U + 20AC:
      • № 8364
      • UTF-8: E2 82 AC
      • UTF-16: 20 AC
    • U + 2122 ЗНАК ТОРГОВОЙ МАРКИ:
      • № 8482
      • UTF-8: E2 84 A2
      • UTF-16: 21 22
    • U + 2603 Снеговик:
      • № 9731
      • UTF-8: E2 98 83
      • UTF-16: 26 03
    • U + 260E ЧЕРНЫЙ ТЕЛЕФОН:
      • № 9742
      • UTF-8: E2 98 8E
      • UTF-16: 26 0E
    • U + 2614 ЗОНТИК с каплями дождя:
      • № 9748
      • UTF-8: E2 98 94
      • UTF-16: 26 14
    • U + 263A БЕЛЫЙ УЛЫБАЮЩИЙСЯ ЛИЦО:
      • № 9786
      • UTF-8: E2 98 BA
      • UTF-16: 26 3А
    • U + 2691 ЧЕРНЫЙ ФЛАГ:
      • № 9873
      • UTF-8: E2 9A 91
      • UTF-16: 26 91
    • U + 269B СИМВОЛ АТОМА:
      • № 9883
      • UTF-8: E2 9A 9B
      • UTF-16: 26 9B
    • U + 2708 САМОЛЕТ:
      • № 9992
      • UTF-8: E2 9C 88
      • UTF-16: 27 08
    • U + 271E БЕЛОГО ЛАТИНСКОГО КРЕСТА:
      • № 10014
      • UTF-8: E2 9C 9E
      • UTF-16: 27 1E
    • U + 3020 ПОЧТА МАРКА ЛИЦА:
      • № 12320
      • UTF-8: E3 80 A0
      • UTF-16: 30 20
    • U + 8089 CJK UNIFIED IDEOGRAPH-8089:
      • № 32905
      • UTF-8: E8 82 89
      • UTF-16: 80 89
    • U + 1F4A9 КУКЛА ПОО: 💩
      • №: 128169
      • UTF-8: F0 9F 92 A9
      • UTF-16: D8 3D DC A9
    • U + 1F680 РАКЕТА: 🚀
      • № 128640
      • UTF-8: F0 9F 9A 80
      • UTF-16: D8 3D DE 80

Хорошо, я увлекаюсь ...

Забавные факты:


В блоки кода в UTF-16 в 16 бит. Вы показали их с пробелом в середине, что вводит в заблуждение. Представление UTF-16 для © должно быть 00A9вместо 00 A9(которое будет UTF-16BE).
Роланд Иллиг

Какая разница? НЕ БУДЕТ стоять за большой порядок байтов? Он написал его с прямым порядком байтов, и поэтому файл с большим порядковым номером UTF-16 будет таким же, как UTF-16BE, верно?
HappyPandaFace

6
Исправления: 1) ASCII - 7 бит, байт - 8 бит, так что это намного больше, чем половина. 2) Unicode определяет, как кодировать кодовые точки. UTF-8, UTF-16 и UTF-32 определены в стандарте Unicode.
Джонатан Розен

3
@JonathanRosenne Я думаю, он / она имел в виду, что он использует только половину возможных значений, представляемых 8 битами, а не то, что он использует половину битов.
Ариц Лопес

2
Мне очень нравятся примеры. Они подчеркивают, почему, например, можно предпочесть UTF-16, а не UTF-8. Разработчики различного программного обеспечения могут выбирать разные кодировки в зависимости от того, какие символы Unicode будут использоваться с большей вероятностью. Например, в Китае / Японии UTF-16 (2 байта) имеет для них больше смысла, чем UTF-8, поскольку для кодирования в UTF-8 одним и тем же символам часто требуется вдвое больше байтов
Майк

29

Проще говоря Unicode, это стандарт, который присваивает один номер (так называемая кодовая точка) всем символам мира (он все еще находится в стадии разработки).

Теперь вам нужно представить этот код с помощью байтов, которые называются character encoding. UTF-8, UTF-16, UTF-6способы представления этих персонажей.

UTF-8многобайтовая кодировка символов Символы могут иметь от 1 до 6 байтов (некоторые из них могут не потребоваться прямо сейчас).

UTF-32 каждый символ имеет 4 байта символов.

UTF-16использует 16 битов для каждого символа и представляет только часть символов Unicode, называемых BMP (для всех практических целей этого достаточно). Java использует эту кодировку в своих строках.


10
Unicode - это 21-битный кодовый набор, и 4 байта достаточно для представления любого символа Unicode в UTF-8. UTF-16 использует суррогаты для представления символов вне BMP (базовая многоязычная плоскость); ему нужно 2 или 4 байта для представления любого допустимого символа Unicode. UCS-2 был 16-битным единственным вариантом UTF-16 без поддержки суррогатов или символов вне BMP.
Джонатан Леффлер

1
Ты прав. Оригинальный UTF-8 имел 6 байтов для размещения 32 бит. На самом деле я не хотел усложнять ситуацию, так как его уже спутали с вики-документом :)
Зимбабао

3
В этом ответе говорится, что UTF-16 не может кодировать кодовые точки BMP. Это неверно, так как они могут быть закодированы так же, как в UTF-8, используя суррогатные пары. (Вы должны думать об устаревшей UCS-2 до выхода Unicode 2.0, который кодировал только 16-битные кодовые точки.) Кроме того, Java не совсем использует UTF-16, она использует его модифицированную форму, где кодовая точка 0 кодируется по-разному.
RDB

@rdb - это наоборот. Ответ говорит, что UTF-16 представляет собой БМП.
Николас Барбулеско

3
Я опечатка; Я хотел сказать «не BMP». Ошибка в ответе состоит в том, что он говорит, что UTF-16 представляет символы BMP, что является неточным. UTF-16 может кодировать все символы Юникода - символы не-BMP кодируются с помощью суррогатных пар. Возможно, ответчик был перепутан с UCS-2.
RDB

17

В UTF-8:

1 byte:       0 -     7F     (ASCII)
2 bytes:     80 -    7FF     (all European plus some Middle Eastern)
3 bytes:    800 -   FFFF     (multilingual plane incl. the top 1792 and private-use)
4 bytes:  10000 - 10FFFF

В UTF-16:

2 bytes:      0 -   D7FF     (multilingual plane except the top 1792 and private-use )
4 bytes:   D800 - 10FFFF

В UTF-32:

4 bytes:      0 - 10FFFF

10FFFF является последней кодовой точкой Юникода по определению, и она определена таким образом, потому что это технический предел UTF-16.

Это также самая большая кодовая точка, которую UTF-8 может кодировать в 4 байта, но идея кодирования UTF-8 также работает для 5- и 6-байтовых кодировок, чтобы покрыть кодовые точки до 7FFFFFFF, т.е. половина того, что может UTF-32.


8

В Unicode ответ дается нелегко. Проблема, как вы уже указали, заключается в кодировках.

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

Единственная кодировка, где (на данный момент) мы можем сделать утверждение о размере, это UTF-32. Там всегда 32 бит на символ, хотя я представляю, что кодовые точки подготовлены для будущего UTF-64 :)

Что делает это настолько сложным, это как минимум две вещи:

  1. составные символы, где вместо использования символьной сущности, которая уже акцентирована / диакритически (À), пользователь решил объединить ударение и базовый символ (`A).
  2. кодовые точки. Кодовые точки - это метод, с помощью которого кодировки UTF позволяют кодировать больше, чем обычно позволяет число битов, которое дает им их имя. Например, UTF-8 обозначает определенные байты, которые сами по себе являются недопустимыми, но когда за ним следует действительный байт продолжения, он позволяет описывать символ за пределами 8-битного диапазона 0..255. См. Примеры и сверхдлинные кодировки ниже в статье Википедии о UTF-8.
    • Отличный пример, приведенный здесь, состоит в том, что символ € (кодовая точка U+20ACможет быть представлен в виде трехбайтовой последовательности E2 82 ACили четырехбайтовой последовательности F0 82 82 AC.
    • Оба действительны, и это показывает, насколько сложен ответ, когда речь идет о «Юникоде», а не о конкретной кодировке Юникода, такой как UTF-8 или UTF-16.


4

Ну, я только что поднял страницу Википедии на ней, и во вступительной части я увидел, что «Юникод может быть реализован различными кодировками символов. Наиболее часто используемые кодировки - это UTF-8 (который использует один байт для любых символов ASCII, которые имеют одни и те же кодовые значения в кодировке UTF-8 и ASCII и до четырех байтов для других символов), теперь устаревший UCS-2 (который использует два байта для каждого символа, но не может кодировать каждый символ в текущем стандарте Unicode) "

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

Итак, ваш простой ответ, который вы хотите, это то, что он меняется.


3

Для UTF-16 персонажу нужны четыре байта (две кодовые единицы), если он начинается с 0xD800 или больше; такой персонаж называется «суррогатная пара». Более конкретно, суррогатная пара имеет вид:

[0xD800 - 0xDBFF]  [0xDC00 - 0xDFF]

где [...] указывает двухбайтовую кодовую единицу с заданным диапазоном. Все, что <= 0xD7FF - это одна кодовая единица (два байта). Все>> 0xE000 недопустимо (за исключением маркеров спецификации, возможно).

См. Http://unicodebook.readthedocs.io/unicode_encodings.html , раздел 7.5.



1

Из вики:

UTF-8, 8-битное кодирование с переменной шириной, которое максимизирует совместимость с ASCII;

UTF-16, 16-битное кодирование с переменной шириной;

UTF-32, 32-битное кодирование с фиксированной шириной.

Это три самых популярных разных кодировки.

  • В UTF-8 каждый символ кодируется от 1 до 4 байтов (доминирующее кодирование)
  • В UTF16 каждый символ кодируется от 1 до двух 16-битных слов и
  • в UTF-32 каждый символ кодируется как одно 32-битное слово.

1

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

Для разных целей вам может потребоваться представить это code pointsв байтах (большинство языков программирования так и делают), и вот где Character Encodingначинается.

UTF-8, UTF-16, UTF-32И так далее все Character Encodings, и кодовые точки в наборах Unicode представлены в этих кодировках, по - разному.


UTF-8 кодирование имеет длину переменной ширины, и символы, закодированные в нем, могут занимать от 1 до 4 байт включительно;

UTF-16имеет переменную длину и символы, закодированные в нем, могут занимать 1 или 2 байта (то есть 8 или 16 бит). Это представляет только часть всех символов Unicode, называемых BMP (базовая многоязычная плоскость), и этого достаточно для почти всех случаев. Java использует UTF-16кодирование для своих строк и символов;

UTF-32 имеет фиксированную длину, и каждый символ занимает ровно 4 байта (32 бита).

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.