Обработка символа как байта в Java, разные результаты - PullRequest
3 голосов
/ 14 февраля 2011

Почему два следующих результата отличаются?

bsh % System.out.println((byte)'\u0080');
-128

bsh % System.out.println("\u0080".getBytes()[0]);
63

Спасибо за ваши ответы.

Ответы [ 5 ]

5 голосов
/ 14 февраля 2011

(byte)'\u0080' просто принимает числовое значение кодовой точки, которая не вписывается в byte и, следовательно, подвергается преобразованию сужающего примитива , которое отбрасывает биты, которые не вписываются в байт и, поскольку бит старшего разряда установлен, дает отрицательное число.

"\u0080".getBytes()[0] преобразует символы в байты в соответствии с кодировкой по умолчанию вашей платформы (существует перегруженный метод getBytes(), который позволяет указывать кодировку). Похоже, кодировка по умолчанию вашей платформы не может представлять кодовую точку U + 0080 и заменяет ее на "?" (кодовая точка U + 003F, десятичное значение 63).

3 голосов
/ 14 февраля 2011

Символ Unicode U+0080 <control> не может быть представлен в кодировке вашей системы по умолчанию и поэтому заменяется на ? (код ASCII 0x3F = 63), когда строка кодируется в кодировку по умолчанию на getBytes().

2 голосов
/ 14 февраля 2011

Здесь байтовый массив имеет 2 элемента - это потому, что представление символов Юникода не помещается в 1 байт.

На моей машине массив содержит [-62, -128]. Это потому, что моя кодировка по умолчанию - UTF-8. Никогда не используйте getBytes() без указания кодировки.

1 голос
/ 14 февраля 2011

Если у вас есть символ, который не поддерживает кодировку символов, он превращает его в '?'в ASCII это 63.

try

System.out.println(Arrays.toString("\u0080".getBytes("UTF-8")));

printints

[-62, -128]
0 голосов
/ 14 февраля 2011

На самом деле, если вы хотите получить тот же результат с вызовом toString(), укажите UTF-16_LE в качестве кодировки charset:

bsh %  System.out.println("\u0080".getBytes("UTF-16LE")[0]); 
-128

Строки Java внутренне кодируются как UTF-16, и так какмы хотим, чтобы младший байт был таким же, как для броска char -> byte, здесь мы используем младший порядок байтов.Big endian тоже работает, если мы изменим индекс массива:

bsh %  System.out.println("\u0080".getBytes("UTF-16BE")[1]);
-128
...