2009-03-17 11 views
56

Sto provando a convertire una stringa codificata in java in UTF-8 in ISO-8859-1. Ad esempio, nella stringa 'âabcd' 'â' è rappresentato in ISO-8859-1 come E2. In UTF-8 è rappresentato come due byte. C3 A2, credo. Quando eseguo un getbytes (codifica) e poi creo una nuova stringa con i byte nella codifica ISO-8859-1, ottengo due caratteri diversi. Ã ¢. C'è un altro modo per farlo in modo da mantenere il personaggio lo stesso vale a dire?Conversione da UTF-8 a ISO-8859-1 in Java - come mantenerlo come byte singolo

risposta

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

Farà il trucco. Dalla tua descrizione sembra che tu stia cercando di "memorizzare una stringa ISO-8859-1". Gli oggetti stringa in Java sono sempre codificati implicitamente in UTF-16. Non c'è modo di cambiare quella codifica.

Ciò che si può fare, 'è di ottenere i byte che costituiscono un'altra codifica (usando il metodo .getBytes() come mostrato sopra).

+0

Grazie, questo mi ha aiutato a risolvere il problema durante la creazione di un file: la mia stringa di nome di file conteneva un carattere di avanzamento riga che non ho potuto notare fino a quando ho stampato la stringa nel registro in questo modo: 'string = new String (string.getBytes (" UTF-16 "));' 'Log.d (TAG, stringa);' e ho visto il carattere extra lì –

+0

Grazie per aver specificato che "Gli oggetti stringa in Java sono sempre codificati implicitamente in UTF-16" - questo ha risolto un problema che stavo avendo ed è Eneralmente utile sapere! –

92

Se hai a che fare con la codifica dei caratteri diversi da UTF-16, non si dovrebbero utilizzare java.lang.String o char primitiva - si dovrebbe essere solo con byte[] array o ByteBuffer oggetti. Quindi, è possibile utilizzare java.nio.charset.Charset per la conversione tra codifiche:

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

Grazie mille .. Davvero utile - Luckylak –

+4

Sì, davvero una bella osservazione. In Java, String è esso stesso codificato in UTF-16. Sempre. Non ha senso pensare che le stringhe siano codificate in qualcos'altro. Invece hai dati grezzi (byte) che rappresentano il testo in qualche codifica. Quindi decodificare (usando una codifica) su String (in UTF-16) o da String a byte. Upvoted! –

+0

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

7

Partendo da una serie di byte che codificano una stringa utilizzando UTF-8, crea una stringa da tali dati, quindi ottenere alcuni byte che codifica la stringa in un diverso codifica:

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

questo uscite stringhe ei byte ISO88591 correttamente:

âabcd 
e2 61 62 63 64 
âabcd 

Così l'array di byte non è stato accoppiato con il corretto ENCOD ing:

String failString = new String (utf8bytes, iso88591charset); 

    System.out.println(failString); 

Uscite

âabcd 

(o che, o semplicemente scritto la utf8 byte in un file e leggere altrove come ISO88591)

caratteri
-3

sfrattare non ISO-8859-1 , sarà sostituito da "?" (prima di inviare a un ISO-8859-1 DB con l'esempio):

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

+4

Sostituire tutti i caratteri non ASCII con '?' Sembra una soluzione terribile quando è possibile convertire la stringa senza perderli. – s4y

0

Se si ha la codifica corretta nella stringa, non è necessario fare di più per ottenere i byte per un'altra codifica.

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

uscita:

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

Per la codifica dei file ...

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

Oltre alla risposta di Adam Rosenfield, vorrei aggiungere che array di byte sottostante ByteBuffer.array() rendimenti del tampone, che non è necessariamente "ritagliato" fino all'ultimo carattere.Saranno necessarie ulteriori manipolazioni, come quelle menzionate nella risposta this; in particolare:

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

Questo è quello che mi serviva:

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