Кодировка Java - поврежденные французские символы

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

String frenchReceipt = "RETIR�E"; // The original Text should be "RETIRÉE"

Я перепробовал все возможные комбинации для преобразования строки с использованием кодировки UTF-8 и ISO-8859-1.

String frenchReceipt = "RETIR�E"; // The original Text should be "RETIRÉE"

byte[] b1 = new String(frenchReceipt.getBytes()).getBytes("UTF-8"); 
System.out.println(new String(b1));  // RETIR�E

byte[] b2 = new String(frenchReceipt.getBytes()).getBytes("ISO-8859-1"); 
System.out.println(new String(b2));  // RETIR�E

byte[] b3 = new String(frenchReceipt.getBytes(), "UTF-8").getBytes(); 
System.out.println(new String(b3));  // RETIR?E 

byte[] b4 = new String(frenchReceipt.getBytes(), "UTF-8").getBytes(); 
System.out.println(new String(b4));  //RETIR?E

byte[] b5 = new String(frenchReceipt.getBytes(), "ISO-8859-1").getBytes("UTF-8"); 
System.out.println(new String(b5));  //RETIR�E

byte[] b6 = new String(frenchReceipt.getBytes(), "UTF-8").getBytes("ISO-8859-1"); 
System.out.println(new String(b6));  //RETIR?E

byte[] b7 = new String(frenchReceipt.getBytes(), "UTF-8").getBytes("UTF-8"); 
System.out.println(new String(b7));  //RETIR�E

byte[] b8 = new String(frenchReceipt.getBytes(), "ISO-8859-1").getBytes("ISO-8859-1"); 
System.out.println(new String(b8));  //RETIR�E

Как видите, проблему не решить.

Пожалуйста, порекомендуйте.

Обновление. Сторонний партнер подтвердил, что данные, отправленные в мое приложение, были в кодировке ISO-8859-1.


person R.Almoued    schedule 30.03.2021    source источник
comment
В какой кодировке находится консоль, на которую собирается System.out?   -  person mayamar    schedule 30.03.2021
comment
см. stackoverflow.com/questions/ 6543548 /. Символы � кодируются как EF BF BD, о чем там сказано в ответе.   -  person mayamar    schedule 30.03.2021
comment
@mayamar Кодировка текстового файла по умолчанию: Cp1252. Но я попытался изменить его также на UTF-8 и ISO-8859-1, но это не устранило проблему.   -  person R.Almoued    schedule 30.03.2021


Ответы (1)


� - это просто заменяющий символ (EF|BF|BD UTF-8) и используется для обозначения проблем, когда система не может отобразить правильный символ. Это означает, что у вас нет возможности конвертировать � в É.

frenchReceipt не содержит какой-либо последовательности байтов, которая могла бы быть преобразована в É из-за объявления:

String frenchReceipt = "RETIR�E";

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

byte[] b2 = new String(frenchReceipt.getBytes()).getBytes("ISO-8859-1");
System.out.println(new String(b2));

Итак, если вы прочитаете RETIRÉE байтами из источника данных и получите 52|45|54|49|52|C9|45 (ожидается ISO-8859-1), вы получите правильный результат. Если в источнике данных уже есть байтовая последовательность EF|BF|BD, единственный вариант, который у вас есть, - это поиск и замена, но в этом случае нет разницы между, например, ä и É.

Обновление: данные доставляются по TCP.

new BufferedReader(new InputStreamReader(connection.getInputStream(),"ISO-8859-1"))

решил вопрос.

person Oleksandr    schedule 30.03.2021
comment
Вы можете точно сказать, что мне делать? Я не понял последнюю часть вашего ответа. Но чтобы прочитать RETIRÉE байтами из источника данных и получить 52 | 45 | 54 | 49 | 52 | C9 | 45 ?? - person R.Almoued; 31.03.2021
comment
Ответ на вопрос, как читать, зависит от источника данных (XML, база данных, двоичный поток и т. Д.). Каков реальный источник данных RETIR�E? - person Oleksandr; 31.03.2021
comment
Согласно документу это простой текст в кодировке ISO-8859-1. - person R.Almoued; 31.03.2021
comment
Чтобы прояснить: полученный мной ответ представляет собой серию параметров, разделенных разделителем полей (FS) и заканчивается полем (EOT). Например: 00 [FS] RETIR�E [FS] FR [EOT] Конечно, для FS и EOT нет скобок [], они просто добавлены для удобства чтения. - person R.Almoued; 31.03.2021
comment
Я спросил об источнике данных, чтобы прояснить причину потери некоторых символов. Проблема с рендерингом или источник данных уже поврежден? Так что вопрос для меня все еще открыт. Если бы это был простой текст в кодировке ISO-8859-1, вы бы легко решили проблему. - person Oleksandr; 31.03.2021
comment
Насколько я понимаю, вы работаете с HTTP-ответом. Лучшим вариантом здесь является кодирование записи 00 [FS] RETIRÉE [FS] FR [EOT] с помощью base64 на стороне сервера и декодирование на стороне клиента. В этом случае у вас не будет проблем с нераспознанными персонажами. stackoverflow.com/questions/3538021/why-do-we-use-base64 Также если вы имеете дело с HTTP, попробуйте попросить сервер закодировать ответ headers.put (Accept-Encoding, UTF-8); headers.put (Accept-Encoding, UTF-8); - person Oleksandr; 31.03.2021
comment
Если это просто файл, откройте запись в любом шестнадцатеричном редакторе и убедитесь, что там нет последовательности EF | BF | BD. Нелегко помочь без обрезки реальных данных. - person Oleksandr; 31.03.2021
comment
Это не HTTP, но я подключаюсь к серверу по протоколу TCP, и я использую постоянное открытие / закрытие сокета для каждого запроса и ответа. и в ответе я получил строковый параметр в качестве образца, который я отправил ранее: 00 [FS] RETIR�E [FS] FR [EOT] - person R.Almoued; 31.03.2021
comment
TCP-соединение не имеет понятия кодировки символов. Попробуйте прочитать поток с помощью BufferedReader br = new BufferedReader (new InputStreamReader (connection.getInputStream (), ISO-8859-1)); - person Oleksandr; 31.03.2021
comment
Большое спасибо. Это именно то, о чем я просил. Это решает проблему - person R.Almoued; 31.03.2021