Преобразовать строковое представление шестнадцатеричного байтового массива в строку с символами не ascii в Java - PullRequest
0 голосов
/ 14 апреля 2020

У меня есть строка, отправляемая клиентом в полезной нагрузке как:

"[0xc3][0xa1][0xc3][0xa9][0xc3][0xad][0xc3][0xb3][0xc3][0xba][0xc3][0x81][0xc3][0x89][0xc3][0x8d][0xc3][0x93][0xc3][0x9a]Departms"

Я хочу получить строку, которая "áéíóúÁÉÍÓÚDepartms" . Как я могу сделать это в Java?

Проблема в том, что я не могу контролировать способ, которым клиент кодирует эту строку. Похоже, что клиент просто кодирует символы не-ascii в этом формате и отправляет символы ascii как есть (см. «Отдел» в конце).

Ответы [ 2 ]

1 голос
/ 14 апреля 2020

Материал в квадратных скобках, похоже, представляет собой символы, закодированные в UTF-8, но странным образом преобразованные в шестнадцатеричную строку. Что вы можете сделать, так это найти каждый экземпляр, который выглядит как [0xc3], и преобразовать его в соответствующий байт, а затем создать новую строку из байтов.

К сожалению, хороших инструментов для работы с байтовыми массивами нет. Вот быстрое и грязное решение, которое использует регулярное выражение для поиска и замены этих шестнадцатеричных кодов соответствующим символом в латинице-1, а затем исправляет это путем повторной интерпретации байтов.

String bracketDecode(String str) {
    Pattern p = Pattern.compile("\\[(0x[0-9a-f]{2})\\]");
    Matcher m = p.matcher(str);
    StringBuilder sb = new StringBuilder();
    while (m.find()) {
        String group = m.group(1);
        Integer decode = Integer.decode(group);
        // assume latin-1 encoding
        m.appendReplacement(sb, Character.toString(decode));
    }
    m.appendTail(sb);
    // oh no, latin1 is not correct! re-interpret bytes in utf-8
    byte[] bytes = sb.toString().getBytes(StandardCharsets.ISO_8859_1);
    return new String(bytes, StandardCharsets.UTF_8);
}
0 голосов
/ 15 апреля 2020

РЕДАКТИРОВАТЬ - у этого ответа есть несколько проблем - я рекомендую НЕ использовать его.

Первые два шестнадцатеричных значения в вопросе - 0xc3 и 0xa1. Они представляют кодировку UTF-8 для буквы á.

. Метод Integer.byteValue() может использоваться для преобразования целого числа в байт. Объедините это с Integer.decode(), который принимает шестнадцатеричные строки (например, "0xc3"), и мы можем сделать следующее:

Integer.decode("0xc3").byteValue();

Затем, используя приведенный выше подход и предполагая общая строка UTF-8:

private static String myDecoder(String str) {
    String[] myBytesStr = str.replace("[", "").split("]");
    int len = myBytesStr.length -1; // last element is not hex, just chars
    byte[] myBytes = new byte[len];
    for (int i = 0; i < len; i++) {
        myBytes[i] = Integer.decode(myBytesStr[i]).byteValue();
    }
    return new String(myBytes, StandardCharsets.UTF_8) + myBytesStr[len];
}

Для ввода, приведенного в вопросе, возвращается:

áéíóúÁÉÍÓÚDepartms
...