Конвертировать строку ISO8859 в UTF8? ÄÖÜ => Ã почему? - PullRequest
6 голосов
/ 30 мая 2011

В чем проблема с этим кодом? Я сделал строку ISO8859. Таким образом, большинство ÄÖÜ - это какой-то крипо-выход. Все в порядке. Но как преобразовать их обратно в обычные символы (UTF8 или что-то)?

    String s = new String("Üü?öäABC".getBytes(), "ISO-8859-15");

    System.out.println(s);
    //ÃÃŒ?öÀABC => ok(?)
    System.out.println(new String(s.getBytes(), "ISO-8859-15"));
    //ÃÂÃÅ?öÃâ¬ABC => ok(?)
    System.out.println(new String(s.getBytes(), "UTF-8"));
    //ÃÃŒ?öÀABC => huh?

Ответы [ 7 ]

7 голосов
/ 31 августа 2012

Я надеюсь, что это решит вашу проблему.

String readable = "äöüÄÖÜßáéíóúÁÉÍÓÚàèìòùÀÈÌÒÙñÑ";

try {
    String unreadable = new String(readable.getBytes("UTF-8"), "ISO-8859-15");
    // unreadable -> äöüÃÃÃÃáéíóúÃÃÃÃÃà èìòùÃÃÃÃÃñÃ
} catch (UnsupportedEncodingException e) {
    // handle error
}

И:

String unreadable = "äöüÃÃÃÃáéíóúÃÃÃÃÃà èìòùÃÃÃÃÃñÃ";

try {
    String readable = new String(unreadable.getBytes("ISO-8859-15"), "UTF-8");
    // readable -> äöüÄÖÜßáéíóúÁÉÍÓÚàèìòùÀÈÌÒÙñÑ
} catch (UnsupportedEncodingException e) {
    // ...
}
7 голосов
/ 30 мая 2011

Конструкция, такая как new String("Üü?öäABC".getBytes(), "ISO-8859-15");, является почти всегда ошибкой.

Здесь вы берете объект String, получаете соответствующий byte[] в кодировке по умолчанию для платформы и интерпретируете его как ISO-8859-15, чтобы преобразовать его обратно в String.

Если кодировка платформы по умолчанию соответствует ISO-8859-15 (или достаточно близко, чтобы не иметь значения для этого конкретного String, например, ISO-8859-1), то это не работает (то есть не имеет реального эффекта).

Во всех остальных случаях наиболее вероятно уничтожит String.

Если вы пытаетесь «исправить» String, то вы, вероятно, слишком поздно: если вам нужно использовать определенную кодировку для чтения данных, тогда вы должны использовать ее в точка, в которой двоичные данные преобразуются в String данные . Например, если вы читаете из InputStream, вам нужно передать правильную кодировку в конструктор InputStreamReader.

.

Попытка решить проблему "по факту" будет

  1. труднее сделать и
  2. часто даже невозможно (потому что декодирование byte[] с неправильным кодированием может быть разрушительной операцией).
4 голосов
/ 30 мая 2011
String s = new String("Üü?öäABC".getBytes(), "ISO-8859-15"); //bug

Весь этот код - поврежденные данные.Он транскодирует данные UTF-16 в системную кодировку (что бы это ни было) и получает эти байты, делает вид, что они действительны ISO-8859-15, и транскодирует их в UTF-16.

Тогда какпреобразовать входную строку типа "Ãà AB? öà € ABC" в обычный?(если я знаю, что строка взята из файла ISO8859).

Правильный способ выполнения этой операции будет выглядеть следующим образом:

byte[] iso859_15 = { (byte) 0xc3, (byte) 0xc3, (byte) 0xbc, 0x3f,
  (byte) 0xc3, (byte) 0xb6, (byte) 0xc3, (byte) 0xa4, 0x41, 0x42,
         0x43 };
String utf16 = new String(iso859_15, Charset.forName("ISO-8859-15"));

Строки в Java всегда UTF-16.Все остальные кодировки должны быть представлены с использованием типа byte.

Теперь, если вы используете System.out для вывода результирующей строки, она может отображаться некорректно, но это другая проблема транскодирования.Например, кодировка консоли Windows по умолчанию не соответствует кодировке системы.Кодировка, используемая System.out, должна соответствовать кодировке устройства, получающего данные.Вы также должны позаботиться о том, чтобы вы читали исходные файлы с той же кодировкой, которую использует ваш редактор.

Чтобы понять, как меняется обработка символьных данных междуязыки читать это .

2 голосов
/ 13 июня 2016

Вот простой способ вывода строки (я создал метод для этого):

public static String (String input){
String output = "";
try {
    /* From ISO-8859-1 to UTF-8 */
    output = new String(input.getBytes("ISO-8859-1"), "UTF-8");
    /* From UTF-8 to ISO-8859-1 */
    output = new String(input.getBytes("UTF-8"), "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
}
return output;

}

// Example
input = "Música";
output = "Música";

это работает !!:)

1 голос
/ 30 мая 2011

Java-строки внутренне всегда хранятся как массивы UTF16 (и как UTF8 в файле классов после компиляции), поэтому вы не можете просто интерпретировать строку, как если бы она была байтовым массивом. Если вы хотите создать байтовый массив из строки в определенной кодировке, вы должны сначала преобразовать в эту кодировку:

byte[] b = "Üü?öäABC".getBytes("ISO-8859-15");

System.out.println(new String(b, "ISO-8859-15")); // will be ok
System.out.println(new String(b, "UTF-8")); // will look garbled
0 голосов
/ 30 мая 2018

это решение работает для меня, я надеюсь, что это поможет вам

String s1 = "l'épargne";
String s2 = new String(s1.getBytes("iso-8859-1"), "utf8");
0 голосов
/ 24 июня 2014

Я хотел бы предоставить расширенный набор символов для проверки преобразованных строк из ISO-8859-1 в utf-8.

@Test
public void testEnc() throws UnsupportedEncodingException {
    String isoString = "äö";
    String utfString = new String(isoString.getBytes("ISO-8859-1"), "utf-8");
    boolean validConvertion = containsSpecialCharacter(utfString);
    assertTrue(validConvertion);
}

public boolean containsSpecialCharacter(String str) {
    String[] readable = new String[] { "Ã", "Ã", "Ñ", "Ò", "Ó", "Ô", "Õ", "Ö", "×", "Ø", "Ù", "Ú", "Û", "Ü", "Ã", "Þ", "ß",
            "à", "á", "â", "ã", "ä", "å", "æ", "ç", "è", "é", "ê", "ë", "ì", "í", "î", "ï", "ð", "ñ", "ò", "ó", "ô", "õ", "ö",
            "÷", "ø", "ù", "ú", "û", "ü", "ý", "þ", "ÿ" };
    for (String st : readable) {
        if (str.contains(st)) {
            return true;
        }
    }
    return false;
}
...