2009-03-17 7 views
56

Ich versuche, eine Zeichenfolge in Java in UTF-8 in ISO-8859-1 codiert zu konvertieren. Sagen Sie zum Beispiel, in der Zeichenkette 'âabcd' 'â' wird in ISO-8859-1 als E2 dargestellt. In UTF-8 wird es als zwei Bytes dargestellt. C3 A2 Ich glaube. Wenn ich ein getbytes mache (Kodierung) und dann eine neue Zeichenfolge mit den Bytes in ISO-8859-1 Kodierung erstelle, bekomme ich zwei verschiedene Zeichen. Ã ¢. Gibt es einen anderen Weg, dies zu tun, um den Charakter gleich zu halten, d.h. âabcd?Konvertieren von UTF-8 zu ISO-8859-1 in Java - wie es als einzelnes Byte zu halten

Antwort

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

Wird den Trick machen. Aus Ihrer Beschreibung geht hervor, dass Sie versuchen, eine ISO-8859-1-Zeichenfolge zu speichern. String-Objekte in Java sind immer implizit in UTF-16 codiert. Es gibt keine Möglichkeit, diese Codierung zu ändern.

Was Sie tun können ', ist jedoch, um die Bytes zu erhalten, die eine andere Kodierung davon darstellen (mit der .getBytes() Methode, wie oben gezeigt).

+0

Danke, das hat mir geholfen, das Problem zu beheben, wenn Sie eine Datei erzeugen: meine Dateinamen-String enthalten einen Zeilenvorschub Zeichen, das ich nicht feststellen konnte bis ich die string in log wie folgt gedruckt: 'string = new String (string.getBytes (" UTF-16 "));' 'Log.d (TAG, string);' und ich sah das extra Zeichen dort –

+0

Danke für die Angabe, dass "String-Objekte in Java immer implizit in UTF-16 codiert sind" - dies löste ein Problem, das ich hatte und ist g im Allgemeinen nützlich zu wissen! –

92

Wenn Sie mit Zeichenkodierungen andere als UTF-16, zu tun, die Sie sollten nicht java.lang.String oder die char mit primitiven - Sie nur byte[] Arrays oder ByteBuffer Objekte sein sollten verwenden. Dann können Sie java.nio.charset.Charset verwenden, um zwischen Codierungen zu konvertieren:

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

Vielen Dank .. Wirklich hilfreich - Luckylak –

+4

Ja wirklich gute Bemerkung. In Java ist String selbst in UTF-16 codiert. Immer. Es macht keinen Sinn, an Strings zu denken, die in etwas anderem kodiert sind. Stattdessen haben Sie Rohdaten (Bytes), die Text in einer Kodierung darstellen. Dann dekodieren Sie (mit einer Codierung) zu String (in UTF-16) oder von String zu Bytes. Upvoted! –

+0

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

7

mit einem Satz von Bytes Start die einen String mit UTF-8-Codierung, eine Zeichenfolge aus diesen Daten erstellt, erhalten dann einige Bytes codiert, die Zeichenfolge in einem anderen Codierung: richtig

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

diese Ausgänge Strings und das ISO88591 Bytes:

âabcd 
e2 61 62 63 64 
âabcd 

So Ihr Byte-Array wurde nicht mit dem richtigen encod gepaart ing:

String failString = new String (utf8bytes, iso88591charset); 

    System.out.println(failString); 

Ausgänge

âabcd 

(entweder das, oder Sie schrieb nur die UTF-8-Bytes in eine Datei und lesen Sie sie an anderer Stelle als ISO88591)

-3

evict nicht ISO-8859-1 Zeichen , wird ersetzt durch '?' (vor dem Senden an eine ISO-8859-1 DB durch Beispiel):

utf8String = neue Zeichenfolge (utf8String.getBytes(), "ISO-8859-1");

+4

Ersetzen alle Nicht-ASCII-Zeichen mit "?" Scheint eine schreckliche Lösung, wenn es möglich ist, die Zeichenfolge zu konvertieren, ohne sie zu verlieren. – s4y

0

Wenn Sie die richtige Codierung in der Zeichenfolge haben, müssen Sie nicht mehr tun, um die Bytes für eine andere Codierung zu erhalten.

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(); 
} 

Ausgang:

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

Für Dateien Codierung ...

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

Neben Adam Rosenfield Antwort, würde ich das ByteBuffer.array() kehrt der zugrunde liegenden Byte-Array hinzufügen, Puffer, was nicht unbedingt bis zum letzten Zeichen getrimmt wird.Eine zusätzliche Manipulation wird benötigt, wie die in this Antwort genannten; insbesondere:

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

Das ist, was ich brauchte:

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