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

Я совершенно смущен концепцией кодирования символов.

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

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

Ответ 1

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

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

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

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

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

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

Ответ 2

ASCII является фундаментальным

Первоначально 1 символ всегда хранился как 1 байт. Байт (8 бит) может различать 256 возможных значений. Но на самом деле использовались только первые 7 бит. Таким образом, было определено только 128 символов. Этот набор известен как набор символов ASCII.

  • 0x00 - 0x1F содержат коды рулевого управления (например, CR, LF, STX, ETX, EOT, BEL,...)
  • 0x20 - 0x40 содержат числа и знаки препинания
  • 0x41 - 0x7F содержат в основном буквенные символы
  • 0x80 - 0xFF 8-й бит = undefined.

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

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

Популярный вопрос: "Является ли ASCII набором символов или это кодировка" ? ASCII - это набор символов. Однако в программировании charset и encoding дико используются как синонимы. Если я хочу обратиться к кодировке, содержащей только символы ASCII и ничего больше (восьмой бит всегда равен 0): US-ASCII.

Unicode идет еще на один шаг

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

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

GBK - это кодировка, которая, как и UTF-8, использует несколько байтов. Первый байт следует стандарту ASCII, поэтому используются только 7 бит. 8-й бит используется для указания наличия 2-го байта, который используется для представления около 22 000 иероглифов. Но важным отличием является то, что этот не учитывает набор символов Unicode.

Типы Mime

Типы Mime также часто смешиваются с кодировками.

Нет простого способа декодирования файла. Было бы идеально, если бы все файлы содержали префикс, чтобы указать, в какой кодировке были сохранены их данные. В конце концов, это зависит от приложения (или его разработчика) для определения кодирования (например, US-ASCII, UTF-8, некоторые системные значения по умолчанию...).

При отправке данных через Интернет существует одна и та же проблема. К счастью, некоторые протоколы, такие как HTTP, используют объявления типа mime, чтобы указать, какие данные и кодировка используют данные. Типичный HTTP-заголовок содержит следующее:

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

Но для text/xml это было бы бессмысленно (параметр charset будет даже проигнорирован). XML-синтаксисы вообще будут читать первую строку файла, ища тег <?xml encoding=..... Если он там, то они снова откроют файл, используя эту кодировку.

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

Ярлыки

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

  • байт сохраняется как подписанный байт (диапазон: -128 до 127).
  • Тип char в java хранится в двух неподписанных байтах (диапазон: 0 - 65535)
  • поток возвращает целое число в диапазоне от -1 до 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);

Ярлык в java - это использование читателей и писателей и указание кодировки при их создании.

// 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 проверяет атрибут кодирования.

Ответ 3

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

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

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

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