ISO-8859-1 кодирование и сохранение двоичных данных
Я прочитал в комментарии к ответу @Esailija на мой вопрос,
ISO-8859-1 – единственное кодирование для полного сохранения исходных двоичных данных с точными байтовыми совпадениями codepoint
Я также прочитал в этом ответе @AaronDigulla, что:
- Android: проблемы с Unicode / Charset при отправке SMS (sendTextMessage)
- Как распознавать символы UTF-8 в кодированном латинском столбце - MySQL
- В чем разница между UTF-8 и ISO-8859-1?
- Как поддерживать кодировку UTF-8 в Eclipse
- Как определить правильную кодировку для read.csv?
В 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]
Вопросов
- Я признаю, что я не совсем понял – почему он не получает байты в коде выше ?
- Самое главное, где это ( задание сохранения байтов
ISO-8859-1
) указано – ссылки на источник, или JSL будет приятным. Это единственная кодировка с этим свойством? - Связано ли это с
ISO-8859-1
по умолчанию ?
См. Также этот вопрос для хороших примеров встречных примеров из других кодировок.
- Сохранить данные на арабском языке в базе данных MySQL
- Как установить кодировку в .getJSON JQuery
- Что такое кодировка символов String в Java?
- Проблемы с кодировкой символов Visual Studio C ++
- Значение -
- utf 8 charset не работает с javax mail
- Преобразование Unicode в ASCII без ошибок в Python
- В чем разница между кодировками utf8mb4 и utf8 в mysql?
"\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]
для произвольных двоичных данных, где str
– new String(bytes, "ISO-8859-1")
а bytes
– это byte[]
.
Это также не имеет ничего общего с Java. Я понятия не имею, что означает его комментарий, это свойства кодировок символов, а не языки программирования.