Сдвиг бит и преобразование символа в escape-строку Юникода - PullRequest
3 голосов
/ 01 декабря 2011

Я нашел класс Java, который конвертирует байты или символы в шестнадцатеричное значение.Но я не могу понять код ясно.Можете ли вы объяснить, что делает код или где я могу найти больше ресурсов по этому поводу?

public class UnicodeFormatter {

    static public String byteToHex(byte b) {
        // Returns hex String representation of byte b
        char hexDigit[] = {
            '0', '1', '2', '3', '4', '5', '6', '7',
            '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
        };
        char[] array = {hexDigit[(b >> 4) & 0x0f], hexDigit[b & 0x0f]};
        return new String(array);
    }

    static public String charToHex(char c) {
        // Returns hex String representation of char c
        byte hi = (byte) (c >>> 8);
        byte lo = (byte) (c & 0xff);
        return byteToHex(hi) + byteToHex(lo);
    }
} // class

Ответы [ 2 ]

4 голосов
/ 01 декабря 2011

Во-первых, давайте начнем с некоторых определений:

  • A char в Java занимает 2 байта ;
  • Каждая byte состоит из 8 бит ;
  • Каждая шестнадцатеричная цифра представляет 4 двоичные цифры или биты ;

Следовательно, byte может быть представлено 2 шестнадцатеричным цифрами, то есть двумя группами по 4 бита.Это именно то, что делается в методе byteToHex: он сначала разбивает байт на две группы по 4 бита, а затем отображает каждую в шестнадцатеричный символ, используя массив hexDigit.Поскольку десятичное значение каждой группы из 4 битов никогда не может быть больше или равно 16 (2^4), каждая группа всегда будет иметь отображение в массиве hexDigits.

Например, предположим, что вы хотитедля преобразования числа 29 в шестнадцатеричное:

  1. 29 представляется в двоичном виде как 00011101;
  2. Разделение 00011101 на две группы по 4-битным выходам 0001 и 1101;
  3. Программно первая группа, 0001, может быть получена путем удаления наименьших значащих 4 бит (1101) из двоичного представления 29.Тогда 0001 станет первым 4 битом.Это выполняется в Java с помощью (b >> 4);
  4. Вторая группа получается из b & 0x0f, что эквивалентно 00011101 & 00001111 = 00001101 = 1101.С помощью бита - AND двоичного числа с 0x0f вы очищаете (устанавливая в 0) все, кроме младших 4 битов.
  5. Наконец, каждая группа преобразуется в десятичное число, получая 1 (0001) и 13 (1101), которые затем отображаются в 1 и D соответственно в шестнадцатеричной системе.
  6. Следовательно, число 29 представляется как1D в шестнадцатеричном формате.

Аналогичная логика может быть применена к методу charToHex.Единственное отличие состоит в том, что вместо преобразования одного байта вы преобразовываете 2, поскольку char составляет 2 байта.

2 голосов
/ 01 декабря 2011

По сути, это то же самое, что превращать 23 в строку, изменив ее на 2 * 10 + 3, затем превратив 2 и 3 в символы.

Чтобы разбить его, сначала разделим на 16, так как мы работаем в шестнадцатеричном формате.

b >> 4 означает сдвиг битов на 4 пробела, поэтому

12345678 >> 4 = 00001234  

тогда значение в позициях 1234 ищется в массиве hexDigit.

Затем мы выполняем операцию модуля, также известную как получение остатка. В десятичном примере это нахождение 3, отрубая все налево. Для двоичного кода они используют AND здесь.

0x0f в битах равно 00001111, поэтому, когда AND с байтом, он изменит 4 левых пробела на 0, оставив только правые 4.

12345678 & 0x0f = 00005678

и снова мы ищем значение в позициях 5678 в массиве hexDigit. Обратите внимание, что я использую 1-8 в качестве маркеров положения, фактические данные будут все 0 и 1.

Редактировать: Вторая функция в основном выполняет ту же операцию, она использует те же функции >>> и &, чтобы разбить символ Юникода на байты. По-видимому, предполагается, что символ Юникода равен 16 битам, поэтому он сдвигает его на 8 позиций, чтобы получить левые 8 бит, и использует & 0xff, чтобы получить правильные 8 бит.

...