2011-05-30 46 views
6

¿Cuál es el problema con este código? Hice una cadena ISO8859. Entonces, la mayoría de los ... son algunos krypooutput. Esta bien. Pero, ¿cómo convertirlos a caracteres normales (UTF8 o algo así)?¿Convertir cadena ISO8859 a UTF8? ÄÖÜ => ¿Por qué?

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? 
+0

Suponiendo que "krypooutput" significa salida de una función criptográfica, ¿por qué intenta convertirla en "caracteres normales"? Eso es inseguro, ya que daría lugar a la pérdida de datos. Si necesita una forma legible por humanos de esa información, use codificación hexadecimal o codificación url. –

+1

No existe la "Cadena ISO8859" en Java. Ver http://balusc.blogspot.com/2009/05/unicode-how-to-get-characters-right.html – axtavt

+0

Entonces, ¿cómo convertir una cadena de entrada como "ÃÃŒ? öà ABC" a la normalidad? (si sé que la cadena es de un archivo ISO8859). – Lissy

Respuesta

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

Todo este código hace es alterar los datos. Transcodifica datos UTF-16 a la codificación del sistema (lo que sea que sea) y toma esos bytes, pretende que son válidos ISO-8859-15 y los transcodifica a UTF-16.

¿Entonces cómo convertir una cadena de entrada como "ÃÃŒ? öà ABC" a la normalidad? (si sé que la cadena es de un archivo ISO8859).

La forma correcta de realizar esta operación sería así:

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")); 

cadenas en Java son siempre la codificación UTF-16. Todas las demás codificaciones se deben representar utilizando el tipo byte.

Ahora, si usa System.out para generar la cadena resultante, puede que no aparezca correctamente, pero ese es un problema de transcodificación diferente. Por ejemplo, la codificación predeterminada Windows console no coincide con la codificación del sistema. La codificación utilizada por System.out debe coincidir con la codificación del dispositivo que recibe los datos. También debe asegurarse de que sea reading your source files con la misma codificación que está usando su editor.

Para comprender cómo el tratamiento de los datos de caracteres varía según los idiomas, lea this.

+1

No debería ser que la matriz de bytes contenga 'ÃÃŒ? öà ABC ABC codificada como ISO-8859-15, que quizás no sea la cadena que desea el OP. 'Üü? ÖäABC' codificado como ISO-8859-15 sería la matriz' {0x22, (byte) 0xdc, (byte) 0xfc, 0x3f, (byte) 0xf6, (byte) 0xe4, 0x41, 0x42, 0x43, 0x22} ' – McDowell

7

Una construcción como new String("Üü?öäABC".getBytes(), "ISO-8859-15"); es casi siempre un error.

Lo que estamos haciendo aquí es tomar un objeto String, para obtener el correspondiente byte[] en el defecto plataforma de codificación y re-interpretarlo como ISO-8859-15 para convertir de nuevo a un String.

Si sucede la codificación predeterminada plataforma para ser ISO-8859-15 (o lo suficientemente cerca para no hacen ninguna diferencia para este particular String, por ejemplo ISO-8859-1), entonces es un no-op (es decir, no tiene ningún efecto real).

En todos los demás casos muy probablemente destruir el String.

Si intenta "fijar" un String, entonces usted está probablemente demasiado tarde: si tiene que utilizar una codificación específica para leer los datos, entonces se debe utilizar en el punto donde se convierte en datos binarios a String datos. Por ejemplo, si lee desde InputStream, debe pasar la codificación correcta al constructor del InputStreamReader.

Tratando de solucionar el problema "después del hecho" será

  1. más difícil de hacer y
  2. menudo ni siquiera es posible (porque decodificar un byte[] con la codificación incorrecta puede ser una operación destructiva).
1

Las cadenas de caracteres Java se almacenan internamente como arreglos UTF16 (y como UTF8 en el archivo de clase después de la compilación), por lo que no puede interpretar simplemente una cadena como si fuera una matriz de bytes. Si desea crear una matriz de bytes de una cadena en una determinada codificación, primero debe convertir en esta codificación:

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 
6

espero que esto va a resolver su problema.

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

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

Y:

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

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

Hola Jooce, probé lo mismo, parece que está funcionando bien, gracias por esto – Sundhar

0

me gustaría proporcionar el conjunto extendido de caracteres para validar cadenas convertidas de la norma ISO-8859-1 en 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; 
} 
2

Aquí es una manera fácil con String salida (he creado un método para hacer esto):

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"; 

funciona !! :)

Cuestiones relacionadas