Связь между юникодом и UTF-8/16/32

808
Tyler Durden

Я не понимаю взаимосвязи между UTF-8 и его другими вариантами и получаю аномальные результаты на терминале. Например, стрелка вправо:

0xE2 0x86 0x92 в UTF-8

но это

0x2192 в UTF-16 в UTF-16 и Unicode

Я не понимаю, как E28692 эквивалентен 2192.

Кроме того, версия UTF-8, похоже, не работает в моем терминале Linux, который использует кодировку UTF-8 со шрифтом DejaVu, который поддерживает Unicode. Например, если я введу

echo -e "\u2192"

Тогда я получаю стрелу, отлично, правильно, это работает. Но если я войду

echo -e "\xe2\x86\x92" или же

echo -e "\x00\x00\x21\x92"

Тогда я получаю неправильную графику. Почему мои шестнадцатеричные последовательности неверны?

1
Вы путаете кодировку и кодировку, чтобы закодировать символы этой кодировки [Абсолютный минимум, который должен знать каждый разработчик программного обеспечения о юникоде и наборах символов (без оправданий!] (Http://www.joelonsoftware.com/articles/Unicode .html) phuclv 9 лет назад 1
https://stackoverflow.com/questions/222386/what-do-i-need-to-know-about-unicode phuclv 9 лет назад 1
«Я не понимаю, как E28692 эквивалентен 2192». Это утверждение недействительно. Проблема в том, что одно не * равно * другому, а одно ** сопоставлено ** с другим. К сожалению, я тоже до сих пор не знаю, существует ли какая-либо формулярная функция отображения или это просто гигантская справочная таблица. Судя по тому, что я могу сказать, в этом есть какая-то логика (https://tools.ietf.org/html/rfc3629#section-4) (хотя это и не очень легко). Synetech 8 лет назад 0

2 ответа на вопрос

2
gronostaj

Unicode is a character set. UTF are encodings.

Unicode defines a set of characters with corresponding code points, ie. values that unambiguously identify characters in Unicode character set.

For example according to unicode-table.com U+0041 corresponds to capital A, U+03A3 is greek capital sigma (Σ) and U+2603 is a snowman (☃). U+ numbers are code points. Unicode tells us what symbol corresponds to what code point, but doesn't tell us how to encode those code points in bytes.

This is where UTF (Unicode Transformation Format) comes into play. UTF is an encoding: it maps Unicode code points to unambiguous byte sequences.

  • UTF-32 is the "dumb" encoding. All Unicode code points are at most 4 bytes long, so UTF-32 simply interprets code point as a 4-byte number (32-bit, hence the name) with big endian byte order. So U+2603 is encoded as 0x00002603.

    UTF-32 is very simple, but also very redundant. Most commonly used characters fall in ASCII range and are represented by code points 0-127 in Unicode, so in UTF-32-encoded files almost 3 in 4 bytes will be zeros. Almost every English sentence becomes 4 times longer (in bytes) when encoded in UTF-32 instead of ASCII.

  • UTF-8 (very common on the Internet) uses only 1 byte for ASCII characters, so it doesn't introduce any overhead in ASCII-only files (every ASCII file is also a UTF-8 file with the same contents). Other characters require up to 6 bytes.

  • UTF-16 (used by Windows, just to name one example) is a compromise between UTF-32 and UTF-8. Code points are encoded to either 16-bit or 32-bit sequences. It's more redundant than UTF-8 in most cases, but easier to maintain and faster to process.

Different characters may have different representations in different UTF-x encodings. For example UTF-8 sequences may span up to 6 bytes, while UTF-16 sequences are at most 4 bytes long, even though both encode the same character set (Unicode). More fine-grained encodings (UTF-8) use more bits to indicate sequence length, so for high code points encoded values are longer and less optimal.

dsolimano's answer has the explanation of your shell's behavior.

на самом деле UTF-8 будет иметь длину не более 4 байтов для всех кодовых точек Unicode. 5 или 6-байтовая последовательность используется для кодирования значений более 21 бита phuclv 9 лет назад 0
1
dsolimano

Unicode code points encoded into UTF-8

They're equivalent because of https://en.wikipedia.org/wiki/UTF-8#Description, see the algorithm for converting Unicode code points to UTF-8. It goes like this.

Your code point 0x2192, is between U+0800 and U+FFFF. So we use the third row of the table.

 Byte 1 Byte 2 Byte 3 16 U+0800 U+FFFF 3 1110xxxx 10xxxxxx 10xxxxxx 

0x2192 in binary is 0010 0001 1001 0010. Let's plug that in, then convert those back to hex

16 U+0800 U+FFFF 3 11100010 10000110 10010010 3 E 2 8 6 9 2 

E28692 in other words.

Escape sequences in your shell

Now as to why your shell doesn't display the right arrow when you enter a UTF-8 sequence, let's look at the bash manual. Search for the section on the escape sequence \xHH and you'll fint it described as

the eight-bit character whose value is the hexadecimal value HH (one or two hex digits)

So you're asking bash to display three separate two character sequences, probably giving you something like LATIN SMALL LETTER A WITH CIRCUMFLEX, START OF SELECTED AREA, and a private use character of some sort.

Итак, если я хочу ввести код UTF-8 в терминал UTF-8, как мне это сделать? Tyler Durden 9 лет назад 0
Я не думаю, что вы можете с эхом, судя по документации. dsolimano 9 лет назад 0

Похожие вопросы