Скажем, у меня есть смайлик ???? (дьявол).
В 4-байтовом UTF-8 это выглядит так: \u00f0\u009f\u0098\u0088
Однако в Java он будет печатать правильно только так: \ud83d\ude08
Как мне перейти от первого ко второму?
ОБНОВЛЕНИЕ 2
Ответ MNEMO намного проще и отвечает на мой вопрос, поэтому, вероятно, лучше пойти с его решением.
ОБНОВЛЕНИЕ
Спасибо Basil Bourque за рецензию. Это было очень интересно.
Я нашел здесь хорошую ссылку: https://github.com/pRizz/Unicode-Converter/blob/master/conversionfunctions.js (в частности, функция convertUTF82Char ()).
Для тех, кто забредет сюда в будущем, вот как это будет выглядеть на Java:
public static String fromCharCode(int n) {
char c = (char)n;
return Character.toString(c);
}
public static String decToChar(int n) {
// converts a single string representing a decimal number to a character
// note that no checking is performed to ensure that this is just a hex number, eg. no spaces etc
// dec: string, the dec codepoint to be converted
String result = "";
if (n <= 0xFFFF) {
result += fromCharCode(n);
} else if (n <= 0x10FFFF) {
n -= 0x10000;
result += fromCharCode(0xD800 | (n >> 10)) + fromCharCode(0xDC00 | (n & 0x3FF));
} else {
result += "dec2char error: Code point out of range: " + decToHex(n);
}
return result;
}
public static String decToHex(int n) {
return Integer.toHexString(n).toUpperCase();
}
public static String convertUTF8_toChar(String str) {
// converts to characters a sequence of space-separated hex numbers representing bytes in utf8
// str: string, the sequence to be converted
var outputString = "";
var counter = 0;
var n = 0;
// remove leading and trailing spaces
str = str.replaceAll("/^\\s+/", "");
str = str.replaceAll("/\\s+$/", "");
if (str.length() == 0) {
return "";
}
str = str.replaceAll("/\\s+/g", " ");
var listArray = str.split(" ");
for (var i = 0; i < listArray.length; i++) {
int b = parseInt(listArray[i], 16); // alert('b:'+dec2hex(b));
switch (counter) {
case 0:
if (0 <= b && b <= 0x7F) { // 0xxxxxxx
outputString += decToChar(b);
} else if (0xC0 <= b && b <= 0xDF) { // 110xxxxx
counter = 1;
n = b & 0x1F;
} else if (0xE0 <= b && b <= 0xEF) { // 1110xxxx
counter = 2;
n = b & 0xF;
} else if (0xF0 <= b && b <= 0xF7) { // 11110xxx
counter = 3;
n = b & 0x7;
} else {
outputString += "convertUTF82Char: error1 " + decToHex(b) + "! ";
}
break;
case 1:
if (b < 0x80 || b > 0xBF) {
outputString += "convertUTF82Char: error2 " + decToHex(b) + "! ";
}
counter--;
outputString += decToChar((n << 6) | (b - 0x80));
n = 0;
break;
case 2:
case 3:
if (b < 0x80 || b > 0xBF) {
outputString += "convertUTF82Char: error3 " + decToHex(b) + "! ";
}
n = (n << 6) | (b - 0x80);
counter--;
break;
}
}
return outputString.replaceAll("/ $/", "");
}
В значительной степени копия 1 к 1, но она выполняет мою цель.