Понимание кодирования и декодирования Java из String.getBytes

Java

задний план

На выходных думал о принципе String.getBytes. Изучив некоторую информацию, я, наконец, проверил свои идеи с помощью кода. Эта статья не потребует слишком много знаний, связанных с исходным кодом.

Точка знаний

  • Связь между Unicode и UTF-8
  • Исходный код, обратный код, дополнительный код
  • Связь между строками Java и Unicode
  • Изучите String.getBytes и решите проблему искаженных символов
  • Гипотеза демо-верификации

используемые инструменты

преобразование между базами

Таблица кодировки Юникод

Кодовая таблица ГБК

Официальный сайт Юникод

Исходный код, дополнительный код, обратный код

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

Источники изображений:woo woo woo.cn блог на.com/из-за чистоты…

Связь между Unicode и UTF-8

Uincode — это набор символов. Он указывает кодовую точку слова или символа, который мы используем. Кодовые точки хранятся в шестнадцатеричном формате.

Набор символов Unicode указывает кодовую точку 4E00.

Набор символов Unicode определяет кодовую точку для D как 4E01.

Компьютеры распознают только двоичные 0 и 1. UTF-8, с другой стороны, относится к правилам кодирования, которые определяют, как кодовые точки хранятся в двоичном виде.

Существуют и другие правила кодирования Unicode, UTF-16 и UTF-32.

десятичная дробь Диапазон символов Unicode (шестнадцатеричный) Метод кодирования UTF-8 (двоичный)
0-127 0000 0000-0000 007F 0xxxxxxx
128-2047 0000 0080-0000 07FF 110xxxxx 10xxxxxx
2048-65535 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
65536-1114111 0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

В приведенной выше таблице кратко описывается формат, в котором Unicode закодирован в UTF-8.

  • Сначала преобразуйте шестнадцатеричный код черезбазовое преобразованиев десятичном виде
  • Затем используйте десятичное число, чтобы найти диапазон, в котором находится приведенная выше таблица, и получите правило кодирования.
  • Затем преобразуйте кодовую точку в двоичную и замените x от младшего к старшему, чтобы получить исходный код двоичного слова.
  • Преобразуйте исходный двоичный код в хранилище с дополнением до двух.

Строки в java-памяти кодируются в юникоде, то есть внутренней кодировке. Мы можем преобразовать юникод в другие правила, такие как GBK или UTF-8.

Гипотеза проверки кода

Возьмите Чжао в качестве примера.

Код Чжао: 8D75.

Преобразование шестнадцатеричной кодовой точки в десятичную: 36213

36213 находится по адресу 2048-65535, а соответствующий формат кодировки UTF-8: 1110xxxx 10xxxxxx 10xxxxxx

Шестнадцатеричная кодовая точка Чжао 8D75 преобразуется в двоичную 1000.

Заполните двоичный код x в 1110xxxx 10xxxxxx 10xxxxxx и добавьте 0, если этого недостаточно.

11101000 10110101 10110101.

Дополнение трех байтов:

Исходный код: 11101000 10110101 10110101

Код дополнения: 10011000 11001011 11001011

Дополнение до двух соответствует массиву байтов в java: {-24,-75,-75}

@Test
public void run454() throws UnsupportedEncodingException {
    String str ="赵";
    final byte[] bytes = str.getBytes("UTF-8");
    StringBuilder stringBuilder =new StringBuilder();

    for (byte aByte : bytes) {
        stringBuilder.append(aByte).append(",");
    }

    System.out.println(stringBuilder.toString());
}
  • Еще один пример:

И кодовая точка: 4E14

Преобразовать шестнадцатеричный код в десятичный: 19988

19988 находится по адресу 2048-65535, а соответствующий формат кодировки UTF-8: 1110xxxx 10xxxxxx 10xxxxxx

Преобразовать шестнадцатеричный код в двоичный: 100111000010100

Исходный код: 11100100 10111000 10010100

Дополнение: 10011100 11001000 11101100

Массив байтов, соответствующий дополнительному коду: {-28,-72,-108}

@Test
public void run43() throws UnsupportedEncodingException {

    // {-28,-72,-108}
    String str ="且";
    final byte[] bytes = str.getBytes("UTF-8");
    StringBuilder stringBuilder =new StringBuilder();

    for (byte aByte : bytes) {
        stringBuilder.append(aByte).append(",");
    }

    System.out.println(stringBuilder.toString());
}

Транскодирование ГБК

Чжао GBK Code Point: D5D4 Шестнадцатеричная кодовая точка преобразования в двоичный: 1,101,010,111,010,100 Источник: 1,101 010,111 010,100 Дополнение: 1,010,101,110,101,100

Массив байтов, соответствующий дополнительному коду: {-43,-44}

@Test
public void run454() throws UnsupportedEncodingException {
    String str ="赵";
    final byte[] bytes = str.getBytes("GBK");
    StringBuilder stringBuilder =new StringBuilder();

    for (byte aByte : bytes) {
        stringBuilder.append(aByte).append(",");
    }
    // -43,-44
    System.out.println(stringBuilder.toString());
}

Проблема искаженных символов в JAVA

Символы или строки Java используют uincode в качестве внутренней кодировки.

@Test
public void run44() {
    String str="\u0c2c";
//        బ
    System.out.println(str);
//      ✈
    System.out.println("\u2708");
}

Кодировка: строка в байтах.

Декодировать: байты в строку.

Когда мы читаем файл, когда фактически прочитанные байты. Затем формат закодированного файла будет декодирован в байтовую строку. Локальная проблема с мусором, склонна здесь.

Не будь заблуждение искаженной струной в небраться. Эта идея неверна. Мы должны решать байты из предыдущего искаженного.

@Test
public void run100() throws UnsupportedEncodingException {
    String str = "张";
    final byte[] gbks = str.getBytes("GBK");
    final String s = new String(gbks, "UTF-8");
    System.out.println(s);
}

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

Итак, идея состоит в том, чтобы использовать gbks для преобразования метода декодирования для получения строки.

использованная литература

Примечания по кодировке символов Руан Ифэн