Недавно я столкнулся с проблемой кодирования символов, в то время как я искал набор символов и кодировку символов. Это сомнение пришло мне в голову. Кодировка UTF-8 наиболее популярна из-за ее обратной совместимости с ASCII.Since UTF-8 формат кодирования переменной длины, как он различает однобайтовые и двухбайтовые символы. Например, "A ݔ" хранится как "410754" (Unicode для A равен 41, а Unicode для арабского символа - 0754.Как кодировка идентифицирует 41, это один символ и 0754 является еще двухбайтовым символом? Почему он не рассматривается как 4107 как один двубайтовый символ и 54 как однобайтовый символ?
Как кодирование UTF-8 идентифицирует однобайтовые и двухбайтовые символы?
Ответ 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)
Ваш пример Aݔ
, который состоит из кодовых 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), когда они находят эти двоичные шаблоны.
Надеюсь, это кому-нибудь поможет!