Как кодирование UTF-8 идентифицирует однобайтовые и двухбайтовые символы?

Недавно я столкнулся с проблемой кодирования символов, в то время как я искал набор символов и кодировку символов. Это сомнение пришло мне в голову. Кодировка UTF-8 наиболее популярна из-за ее обратной совместимости с ASCII.Since UTF-8 формат кодирования переменной длины, как он различает однобайтовые и двухбайтовые символы. Например, "A ݔ" хранится как "410754" (Unicode для A равен 41, а Unicode для арабского символа - 0754.Как кодировка идентифицирует 41, это один символ и 0754 является еще двухбайтовым символом? Почему он не рассматривается как 4107 как один двубайтовый символ и 54 как однобайтовый символ?

Ответ 1

Например, "A ݔ" сохраняется как "410754"

Это не то, как работает UTF-8.

Символы U + 0000 через U + 007F (aka ASCII) сохраняются как одиночные байты. Они являются единственными символами, чьи кодовые точки численно соответствуют их представлению UTF-8. Например, U + 0041 становится 0x41, который 0100001 в двоичном формате.

Все остальные символы представлены несколькими байтами. U + 0080 через U + 07FF используют по два байта каждый, U + 0800 через U + FFFF используют по три байта каждый, а U + 10000 - U + 10FFFF используют по четыре байта каждый.

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

Из-за этого кодовые точки должны быть закодированы. Рассмотрим следующие двоичные паттерны:

  • 2 байта: 110xxxxx 10xxxxxx
  • 3 байта: 1110xxxx 10xxxxxx 10xxxxxx
  • 4 байта: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

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

В качестве примера: U + 0754 находится между U + 0080 и U + 07FF, поэтому ему нужны два байта. 0x0754 в двоичном формате 11101010100, поэтому вы заменяете x этими цифрами:

110 11101 10 010100

Ответ 2

Короткий ответ:

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

  • 1-байтные коды (все и только символы ASCII) начинаются с 0
  • Ведущие байты двухбайтовых кодов начинаются с двух 1 с, а затем 0 (то есть 110)
  • Ведущие байты 3-байтных кодов начинаются с трех 1 с, а затем 0 (т.е. 1110)
  • Ведущие байты четырехбайтовых кодов начинаются с четырех 1 с, а затем 0 (т.е. 11110)
  • Продолжение байтов (из всех многобайтовых кодов) начинается с единственного 1, за которым следует 0 (т.е. 10)

Ваш пример , который состоит из кодовых U-символов Unicode U + 0041 и U + 0754, кодируется в UTF-8 следующим образом:

0 1000001 110 11101 10 010100

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


Смотрите здесь, как UTF-8 кодирует кодовые точки Unicode.

Ответ 3

Просто для пояснения, ASCII означает стандартный 7-битный ASCII, а не расширенный 8-битный ASCII, который обычно используется в Европе.

Таким образом, часть первого байта (от 0x80 до 0xFF) переходит в двухбайтовое представление, а часть второго байта в два байта (от 0x0800 до 0xFFFF) принимает полное трехбайтовое представление.

Четырехбайтовое представление использует только самые младшие три байта и только 1.114.111 из 16.777.215 доступных возможностей

У вас есть xls здесь

Это означает, что интерпретаторы должны "перескакивать" байт NUL (0), когда они находят эти двоичные шаблоны.

Надеюсь, это кому-нибудь поможет!