“Зафиксируйте” Строковое кодирование в Java

У меня есть a String созданный из a byte[] массив, с помощью кодировки UTF-8.
Однако это должно было быть создано с помощью другого кодирования (Windows 1252).

Существует ли способ преобразовать эту Строку назад в правильное кодирование?

Я знаю, что легко сделать, если у Вас есть доступ к исходному массиву байтов, но это мой случай, слишком поздно, потому что это дано библиотекой с закрытым исходным кодом.

21
задан Joachim Sauer 30 August 2012 в 16:13
поделиться

3 ответа

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

В вопросе утверждается, что (начальным) входом является байт[], который содержит Windows-1252 закодированные данные. Я буду называть это byte[] ib (для "начальных байтов").

Для этого примера я выберу в качестве входных данных немецкое слово "Bär" (что означает медведь):

byte[] ib = new byte[] { (byte) 0x42, (byte) 0xE4, (byte) 0x72 };
String correctString = new String(ib, "Windows-1252");
assert correctString.charAt(1) == '\u00E4'; //verify that the character was correctly decoded.

(Если ваша JVM не поддерживает эту кодировку, то вместо нее можно использовать ISO-8859-1, потому что эти три буквы (и большинство других) находятся на одной позиции в этих двух кодировках).

Далее в вопросе говорится, что какой-то другой код (который находится вне нашего влияния) уже преобразовал этот byte[] в строку, используя кодировку UTF-8 (я буду называть это String is для "входной строки"). Эта String - единственный вход, который доступен для достижения нашей цели (если бы is был доступен, это было бы тривиально):

String is = new String(ib, "UTF-8");
System.out.println(is);

Это, очевидно, дает неправильный выход "B�".

Целью было бы получить ib (или правильную расшифровку этого байта[]) при наличии только is.

Теперь некоторые утверждают, что получение байтов в кодировке UTF-8 из is вернет массив с теми же значениями, что и исходный массив:

byte[] utf8Again = is.getBytes("UTF-8");

Но это вернет кодировку UTF-8 двух символов B и и определенно вернет неверный результат при переинтерпретации в Windows-1252:

System.out.println(new String(utf8Again, "Windows-1252");

Эта строка выдает результат "B�", что совершенно неверно (это также тот же результат, который был бы получен, если бы исходный массив содержал не слово "Bür").

Поэтому в этом случае вы не можете отменить операцию, потому что информация потеряна.

На самом деле есть случаи, когда такие неправильные кодировки можно отменить. Более вероятно, что это сработает, если все возможные (или, по крайней мере, встречающиеся) последовательности байтов действительны в данной кодировке. Поскольку в UTF-8 есть несколько последовательностей байтов, которые просто не являются допустимыми значениями, у вас будут проблемы.

25
ответ дан 29 November 2019 в 21:17
поделиться

Вы можете использовать этот учебник

Нужный вам charset должен быть определен в rt.jar (согласно этому)

-3
ответ дан 29 November 2019 в 21:17
поделиться

То, что вы хотите сделать, невозможно. Как только у вас есть Java String, информация о массиве байтов теряется. Возможно, вам повезет при выполнении "ручного преобразования". Создайте список всех символов windows-1252 и их отображение в UTF-8. Затем переберите все символы в строке, чтобы преобразовать их в нужную кодировку.

Редактировать:. Как сказал один из комментаторов, это не сработает. Если вы преобразуете массив байтов Windows-1252 так, как если бы он был UTF-8, вы обязательно получите исключения кодировки. (См. здесь и здесь).

-1
ответ дан 29 November 2019 в 21:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: