задний план
На выходных думал о принципе 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 для преобразования метода декодирования для получения строки.