2009-03-17 51 views
56

Estoy tratando de convertir una cadena codificada en java en UTF-8 a ISO-8859-1. Digamos, por ejemplo, en la cadena "âabcd '' â 'se representa en ISO-8859-1 como E2. En UTF-8 se representa como dos bytes. C3 A2, creo. Cuando hago un getbytes (codificación) y luego creo una nueva cadena con los bytes en la codificación ISO-8859-1, obtengo dos caracteres diferentes. Ã ¢. ¿Hay alguna otra manera de hacer esto para mantener al personaje igual, es decir, "abcd"?Conversión de UTF-8 a ISO-8859-1 en Java: cómo mantenerlo como un solo byte

Respuesta

29
byte[] iso88591Data = theString.getBytes("ISO-8859-1"); 

Harán el truco. Según su descripción, parece que intenta "almacenar una cadena ISO-8859-1". Los objetos de cadena en Java son siempre codificados implícitamente en UTF-16. No hay forma de cambiar esa codificación.

Lo que puede hacer, 'aunque es obtener los bytes que constituyen alguna otra codificación de la misma (utilizando el método .getBytes() como se muestra arriba).

+0

Gracias, esto me ayudó a resolver el problema al crear un archivo: mi cadena de nombre de archivo contiene un carácter de avance de línea que no podía notar hasta que imprimí la cadena en log como este: 'string = new String (string.getBytes (" UTF-16 "));' 'Log.d (TAG, string);' y vi el personaje extra allí –

+0

Gracias por especificar que "los objetos String en Java siempre están codificados implícitamente en UTF-16" - esto resolvió un problema que estaba teniendo y es g ¡generalmente útil para saber! –

92

Si usted está tratando con la codificación de caracteres que no sean UTF-16, no se debe utilizar java.lang.String o la primitiva char - sólo se debería utilizar byte[] arrays o ByteBuffer objetos. A continuación, puede utilizar java.nio.charset.Charset para convertir entre codificaciones:

Charset utf8charset = Charset.forName("UTF-8"); 
Charset iso88591charset = Charset.forName("ISO-8859-1"); 

ByteBuffer inputBuffer = ByteBuffer.wrap(new byte[]{(byte)0xC3, (byte)0xA2}); 

// decode UTF-8 
CharBuffer data = utf8charset.decode(inputBuffer); 

// encode ISO-8559-1 
ByteBuffer outputBuffer = iso88591charset.encode(data); 
byte[] outputData = outputBuffer.array(); 
+0

Muchas gracias .. Muy útil - Luckylak –

+4

Sí, muy buena observación. En Java, String está codificado en UTF-16. Siempre. No tiene sentido pensar en cadenas codificadas en otra cosa. En su lugar, tiene datos sin procesar (Bytes) que representan texto en alguna codificación. Luego decodifica (usando alguna codificación) a String (en UTF-16), o de String a bytes. ¡Voto ascendente! –

+0

@ Adam Rosenfield: Byte [] ==> byte [] – AndrewBourgeois

7

A partir de un conjunto de bytes que codifican una cadena con UTF-8, crea una cadena partir de esos datos, a continuación, obtener algunos bytes que codifica la cadena en un diferente codificación:

byte[] utf8bytes = { (byte)0xc3, (byte)0xa2, 0x61, 0x62, 0x63, 0x64 }; 
    Charset utf8charset = Charset.forName("UTF-8"); 
    Charset iso88591charset = Charset.forName("ISO-8859-1"); 

    String string = new String (utf8bytes, utf8charset); 

    System.out.println(string); 

    // "When I do a getbytes(encoding) and " 
    byte[] iso88591bytes = string.getBytes(iso88591charset); 

    for (byte b : iso88591bytes) 
     System.out.printf("%02x ", b); 

    System.out.println(); 

    // "then create a new string with the bytes in ISO-8859-1 encoding" 
    String string2 = new String (iso88591bytes, iso88591charset); 

    // "I get a two different chars" 
    System.out.println(string2); 

estas salidas de cuerdas y los bytes ISO88591 correctamente:

âabcd 
e2 61 62 63 64 
âabcd 

Así que su matriz de bytes no fue emparejado con el encod correcta ing:

String failString = new String (utf8bytes, iso88591charset); 

    System.out.println(failString); 

Salidas

âabcd 

(o eso, o que acaba de escribir el UTF-8 bytes en un archivo y leer en otro lugar como ISO88591)

caracteres
-3

evict no ISO-8859-1 , será reemplazado por '?' (antes de enviarlo a una base de datos ISO-8859-1 por ejemplo):

utf8String = new String (utf8String.getBytes(), "ISO-8859-1");

+4

Reemplazar todos los caracteres no ASCII con '?' Parece una solución terrible cuando es posible convertir la cadena sin perderlos. – s4y

0

Si tiene la codificación correcta en la cadena, no necesita hacer más para obtener los bytes para otra codificación.

public static void main(String[] args) throws Exception { 
    printBytes("â"); 
    System.out.println(
      new String(new byte[] { (byte) 0xE2 }, "ISO-8859-1")); 
    System.out.println(
      new String(new byte[] { (byte) 0xC3, (byte) 0xA2 }, "UTF-8")); 
} 

private static void printBytes(String str) { 
    System.out.println("Bytes in " + str + " with ISO-8859-1"); 
    for (byte b : str.getBytes(StandardCharsets.ISO_8859_1)) { 
     System.out.printf("%3X", b); 
    } 
    System.out.println(); 
    System.out.println("Bytes in " + str + " with UTF-8"); 
    for (byte b : str.getBytes(StandardCharsets.UTF_8)) { 
     System.out.printf("%3X", b); 
    } 
    System.out.println(); 
} 

Salida:

Bytes in â with ISO-8859-1 
E2 
Bytes in â with UTF-8 
C3 A2 
â 
â 
0

Para los archivos de codificación ...

public class FRomUtf8ToIso { 
     static File input = new File("C:/Users/admin/Desktop/pippo.txt"); 
     static File output = new File("C:/Users/admin/Desktop/ciccio.txt"); 


    public static void main(String[] args) throws IOException { 

     BufferedReader br = null; 

     FileWriter fileWriter = new FileWriter(output); 
     try { 

      String sCurrentLine; 

      br = new BufferedReader(new FileReader(input)); 

      int i= 0; 
      while ((sCurrentLine = br.readLine()) != null) { 
       byte[] isoB = encode(sCurrentLine.getBytes()); 
       fileWriter.write(new String(isoB, Charset.forName("ISO-8859-15"))); 
       fileWriter.write("\n"); 
       System.out.println(i++); 
      } 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       fileWriter.flush(); 
       fileWriter.close(); 
       if (br != null)br.close(); 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
      } 
     } 

    } 


    static byte[] encode(byte[] arr){ 
     Charset utf8charset = Charset.forName("UTF-8"); 
     Charset iso88591charset = Charset.forName("ISO-8859-15"); 

     ByteBuffer inputBuffer = ByteBuffer.wrap(arr); 

     // decode UTF-8 
     CharBuffer data = utf8charset.decode(inputBuffer); 

     // encode ISO-8559-1 
     ByteBuffer outputBuffer = iso88591charset.encode(data); 
     byte[] outputData = outputBuffer.array(); 

     return outputData; 
    } 

} 
0

Además de la respuesta de Adam Rosenfield, me gustaría añadir que el conjunto de bytes subyacente ByteBuffer.array() rendimientos del búfer, que no necesariamente se "recorta" hasta el último personaje.Se necesitará manipulación adicional, como las que se mencionan en la respuesta this; en particular:

byte[] b = new byte[bb.remaining()] 
bb.get(b); 
1

Esto es lo que necesitaba:

public static byte[] encode(byte[] arr, String fromCharsetName) { 
    return encode(arr, Charset.forName(fromCharsetName), Charset.forName("UTF-8")); 
} 

public static byte[] encode(byte[] arr, String fromCharsetName, String targetCharsetName) { 
    return encode(arr, Charset.forName(fromCharsetName), Charset.forName(targetCharsetName)); 
} 

public static byte[] encode(byte[] arr, Charset sourceCharset, Charset targetCharset) { 

    ByteBuffer inputBuffer = ByteBuffer.wrap(arr); 

    CharBuffer data = sourceCharset.decode(inputBuffer); 

    ByteBuffer outputBuffer = targetCharset.encode(data); 
    byte[] outputData = outputBuffer.array(); 

    return outputData; 
} 
Cuestiones relacionadas