Вопрос по encoding – Что такое кодировка символов и почему я должен беспокоиться об этом

31

Я довольно смущен концепциейcharacter encoding.

Что такое Юникод, ГБК и т. Д.? Как язык программирования использует их?

Нужно ли мне знать о них? Есть ли более простой или быстрый способ программирования, не беспокоясь о них?

Классическим внешним ресурсом для этого является эссе Джоэла СпольскиThe Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!). Raedwald
Это поздний ответ, но я опубликовал некоторые пояснения по поводу упомянутых кодировок и кодировок + также некоторые ярлыки (например, для Java) bvdb

Ваш Ответ

3   ответа
35
ASCII is fundamental

потенциал для различения 256 возможных значений. Но по фактуonly the first 7 bits were used, Таким образом, были определены только 128 символов. Этот набор известен какthe ASCII character set.

0x00 - 0x1F contain steering codes (e.g. CR, LF, STX, ETX, EOT, BEL, ...) 0x20 - 0x40 contain numbers and punctuation 0x41 - 0x7F contain mostly alphabetic characters 0x80 - 0xFF the 8th bit = undefined.

Французский, немецкий и многие другие языки нуждались в дополнительных символах. (например.à, é, ç, ô, ...), которые не были доступны в наборе символов ASCII. Поэтому они использовали 8-й бит для определения своих персонажей. Это то, что известно как & quot;extended ASCII& Quot ;.

Проблема в том, что дополнительный 1 бит не обладает достаточной емкостью для охвата всех языков мира. Таким образом, каждый регион имеет свой вариант ASCII. Есть много расширенных кодировок ASCII (latin-1 будучи очень популярным).

Популярный вопрос:"Is ASCII a character set or is it an encoding" ? ASCII это набор символов. Однако в программированииcharset а такжеencoding дико используются как синонимы. Если я хочу сослаться на кодировку, которая содержит только символы ASCII и ничего более (8-й бит всегда равен 0): это & s;US-ASCII.

Unicode goes one step further

Unicode отличный пример набора символов, а не кодировки, Он использует те же символы, что и стандарт ASCII, но расширяет список дополнительными символами, что дает каждому символу кодовую точку в форматеu+xxxx, Он имеет амбиции содержать всех персонажей (и популярные значки), используемых во всем мире.

UTF-8, UTF-16 and UTF-32 are encodings that apply the Unicode character table. Но у каждого из них есть свой способ кодирования. UTF-8 будет использовать только 1 байт при кодировании символа ASCII, давая тот же вывод, что и любое другое кодирование ASCII. Но для других символов он будет использовать первый бит, чтобы указать, что последует второй байт.

GBK это кодировка, которая так же, как UTF-8 использует несколько байтов. Принцип почти такой же. Первый байт соответствует стандарту ASCII, поэтому используются только 7 бит. Но, как и в UTF-8, 8-й бит может использоваться для указания наличия 2-го байта, который он затем использует для кодирования одного из 22 000 китайских символов. Основное отличие заключается в том, что этоdoes not follow the Unicode character setВ отличие от этого он использует некоторые китайские символы.

Decoding data

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

Unfortunately, encodings aren't always declared or specified. Было бы идеально, если бы все файлы содержали префикс для указания того, в какой кодировке хранятся их данные. Но все же во многих случаях приложения просто должны предполагать или угадывать, какую кодировку им следует использовать. (например, они используют стандартную кодировку операционной системы).

There still is a lack of awareness about this, as still many developers don't even know what an encoding is.

Mime types

Типы пантомимы иногда путают с кодировками. Они являются полезным способом для получателя определить, какие данные поступают. Вот пример того, как протокол HTTP определяет его тип контента с использованием объявления типа mime.

Content-Type: text/html; charset=utf-8

И это еще один великий источник путаницы. MIME-тип описываетwhat kind of data сообщение содержит (например,text/xml, image/png...). И в некоторых случаях это будет также дополнительно описыватьhow данные закодированы (т.е.charset=utf-8). 2 пункта путаницы:

Not all mime types declare an encoding. In some cases it is only optional or sometimes completely pointless. The syntax charset=utf-8 adds up to the semantic confusion, because as explained earlier, UTF-8 is an encoding and not a character set. But as explained earlier, some people just use the 2 words interchangeably.

Например, в случаеtext/xml было бы бессмысленно объявлять кодировку (иcharset параметр будет просто игнорироваться). Вместо,XML parsers in general will read the first line of the file, looking for the <?xml encoding=... tag. Если он там есть, он снова откроет файл, используя эту кодировку.

Та же проблема существуетпри отправке электронной почты, Электронное письмо может содержать HTML-сообщение или просто текст. Также в этом случае MIME-типы используются для определения типа контента.

Но в целом, тип пантомимы не всегда достаточен для решения проблемы.

Data types in programming languages

В случае Java (и многих других языков программирования) в дополнение к опасностям кодировок существует также сложность приведения байтов и целых чисел к символам, поскольку их содержимое хранится в разных диапазонах.

a byte is stored as a signed byte (range: -128 to 127). the char type in java is stored in 2 unsigned bytes (range: 0 - 65535) a stream returns an integer in range -1 to 255.

Если вы знаете, что ваши данные содержат только значения ASCII. Затем, используя соответствующий навык, вы можете анализировать данные из байтов в символы или сразу же переносить их в строки.

// the -1 indicates that there is no data
int input = stream.read();
if (input == -1) throw new EOFException();

// bytes must be made positive first.
byte myByte = (byte) input;
int unsignedInteger = myByte & 0xFF;
char ascii = (char)(unsignedInteger);
Shortcuts

The shortcut in java is to use readers and writers and to specify the encoding when you instantiate them.

// wrap your stream in a reader. 
// specify the encoding
// The reader will decode the data for you
Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);

Как объяснялось ранее для файлов XML, это не имеет большого значения, потому что любой приличный маршаллер DOM или JAXB проверит атрибут кодирования.

Также интересна BOM (метка порядка байтов), которая используется для кодировок, которые используют несколько байтов (например, UTF-16). Он указывает, какой из байтов является первым (наиболее значимым). Этот байт-маркер ставится перед сообщением. Еще одна веская причина использовать приличныйReaders.
Таблица символов Unicodeis кодирование по определению, тем не менее, оно дважды кодируется в i. е. UTF-8. Поэтому просто неправильно, что Unicode не имеет кодировки.
Нет & quot; Acoded Набор символов - это набор символов, для которого каждому персонажу был присвоен уникальный номер. & Quot; Это то же определение, которое я использовал в Википедии. ;-)
@ AminNegm-Awad Я не писал "Юникод"has нет кодировки & quot ;. Unicode имеет кодировки: (например, UTF-8, UTF-16, ... и т. Д.). Это те реализации. Сам Unicode во многом похож на «алфавит», это просто список символов. Вот почему Unicodeis not кодировка. Кодирование, с другой стороны, должно описывать, как информация будет храниться в битах и байтах. - Понятия не имею, что вы имеете в виду под "двойным кодированием" хоть. Вы имеете в виду тот факт, что есть несколько реализаций Unicode? (потому что я согласен с этим).
Небольшое примечание: поскольку почти все кодировки кодируют 128 основных символов ASCII одинаковым образом, при условии, что все используемые символы определены в этом базовом наборе, вы можете фактически кодировать / декодировать свое сообщение, используя практически любое случайное кодирование. (например, UTF-8, US-ASCII, латинский-1, GBK, ...).
36

(Обратите внимание, что я использую некоторые из этих терминов свободно / в разговорной речи для более простого объяснения, которое все еще затрагивает ключевые моменты.

Байт может иметь только 256 различных значений, составляющих 8 битов.

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

Следовательно, должны быть сопоставления, описывающие, как превратить каждый символ в наборе символов в последовательность байтов. Некоторые символы могут быть сопоставлены с одним байтом, но другие должны быть сопоставлены с несколькими байтами.

Эти отображения являются кодировками, потому что они говорят вам, как кодировать символы в последовательности байтов.

Что касается Unicode, на очень высоком уровне Unicode - это попытка назначить один уникальный номер каждому персонажу. Очевидно, что это число должно быть чем-то шире байта, поскольку в нем более 256 символов : Java использует версию Unicode, где каждому символу присваивается 16-битное значение (и именно поэтому символы Java имеют 16-битную ширину и целое число значения от 0 до 65535. Когда вы получаете байтовое представление символа Java, вы должны сообщить JVM кодировку, которую вы хотите использовать, чтобы она знала, как выбрать последовательность байтов для символа.

2

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

Вы не знаете, что это за персонажи и как они упорядочены. Поэтому вы не знаете, как будут выглядеть строки в этом новом языке в двоичном формате, и, честно говоря, вам все равно.

У вас есть способ перевода строк с языка, на котором вы говорите, на язык, на котором они говорят (например, переводчик). Теперь вам нужна система, которая способна представлять оба языка в двоичном формате без конфликтов. Кодировка - это та система.

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

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