ISO-8859-1 кодирование и сохранение двоичных данных

Я прочитал в комментарии к ответу @Esailija на мой вопрос,

ISO-8859-1 – единственное кодирование для полного сохранения исходных двоичных данных с точными байтовыми совпадениями codepoint

Я также прочитал в этом ответе @AaronDigulla, что:

В Java ISO-8859-1 (aka ISO-Latin1) является отображением 1: 1

Мне нужно понять это. Это не сработает (как показано здесь ):

// \u00F6 is ö System.out.println(Arrays.toString("\u00F6".getBytes("utf-8"))); // prints [-61, -74] System.out.println(Arrays.toString("\u00F6".getBytes("ISO-8859-1"))); // prints [-10] 

Вопросов

  1. Я признаю, что я не совсем понял – почему он не получает байты в коде выше ?
  2. Самое главное, где это ( задание сохранения байтов ISO-8859-1 ) указано – ссылки на источник, или JSL будет приятным. Это единственная кодировка с этим свойством?
  3. Связано ли это с ISO-8859-1 по умолчанию ?

См. Также этот вопрос для хороших примеров встречных примеров из других кодировок.

"\u00F6" не является байтовым массивом. Это строка, содержащая один символ. Вместо этого выполните следующий тест:

 public static void main(String[] args) throws Exception { byte[] b = new byte[] {(byte) 0x00, (byte) 0xf6}; String s = new String(b, "ISO-8859-1"); // decoding byte[] b2 = s.getBytes("ISO-8859-1"); // encoding System.out.println("Are the bytes equal : " + Arrays.equals(b, b2)); // true } 

Чтобы проверить, что это верно для любого байта, просто улучшите код за цикл по всем байтам:

 public static void main(String[] args) throws Exception { byte[] b = new byte[256]; for (int i = 0; i < b.length; i++) { b[i] = (byte) i; } String s = new String(b, "ISO-8859-1"); byte[] b2 = s.getBytes("ISO-8859-1"); System.out.println("Are the bytes equal : " + Arrays.equals(b, b2)); } 

ISO-8859-1 является стандартным кодированием. Поэтому используемый язык (Java, C # или что-то еще) не имеет значения.

Вот ссылка на Википедию, в которой утверждается, что каждый байт покрыт:

В 1992 году IANA зарегистрировала карту символов ISO_8859-1: 1987, более известную по своему предпочтительному MIME-названию ISO-8859-1 (обратите внимание на дополнительный дефис по ISO 8859-1), надмножество ISO 8859-1, для использовать в Интернете. Эта карта назначает управляющие символы C0 и C1 ненадлежащим значениям кода, таким образом, обеспечивает 256 символов через каждое возможное 8-битное значение.

(акцент мой)

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

Это исключает все многобайтовые кодировки (UTF-8/16/32, Shift-Jis, Big5 и т. Д.), Потому что не каждая байтовая последовательность в них действительна и, следовательно, будет декодировать некоторый символ замены (обычно? Или ). Невозможно сказать из строки, что послужило причиной замены символа после его декодирования.

Другой вариант – игнорировать недопустимые байты, но это также означает, что бесконечные разные последовательности байтов декодируются в одну и ту же строку. Вы можете заменить недопустимые байты шестнадцатеричной кодировкой в ​​строке типа "0xFF" . Невозможно определить, действительно ли исходные байты законно декодируются до "0xFF" так что это тоже не работает.

Это оставляет 8-битные кодировки, где каждая последовательность представляет собой только один байт. Единый байт действителен, если для него есть отображение. Но многие 8-битные кодировки имеют отверстия и не кодируют 256 разных символов.

Чтобы сохранить исходные двоичные данные, вам потребуется 8-битная кодировка, которая кодирует 256 разных символов. ISO-8859-1 не уникален в этом. Но то, что оно уникально в том, что значение декодированного кода также является значением байта, с которого оно было декодировано.

Итак, у вас есть декодированная строка и закодированные байты, тогда она всегда

 (byte)str.charAt(i) == bytes[i] 

для произвольных двоичных данных, где strnew String(bytes, "ISO-8859-1") а bytes – это byte[] .


Это также не имеет ничего общего с Java. Я понятия не имею, что означает его комментарий, это свойства кодировок символов, а не языки программирования.

  • В чем разница между UTF-8 и UTF-8 без спецификации?
  • Вход Unicode, полученный через входные компоненты PrimeFaces, поврежден
  • Как передать символы Юникода как JSP / Servlet request.getParameter?
  • Кодировка Spring MVC UTF-8
  • Как преобразовать весь набор символов базы данных MySQL и сопоставление с UTF-8?
  • Encoding.UTF8.GetString не учитывает преамбулу / спецификацию
  • Как преобразовать между ISO-8859-1 и UTF-8 в Java?
  • UTF8 в / из широкого преобразования символов в STL
  • Извлечение текста UTF-8 из MySQL в R возвращает «????»
  • Чтение / запись файла .txt со специальными символами
  • Изменить символ по умолчанию MySQL на UTF-8 в my.cnf?
  • Давайте будем гением компьютера.