Codifica stringa in UTF-8


190

Ho una stringa con un carattere "ñ" e ho dei problemi con essa. Devo codificare questa stringa in codifica UTF-8. L'ho provato in questo modo, ma non funziona:

byte ptext[] = myString.getBytes();
String value = new String(ptext, "UTF-8");

Come codifico quella stringa in utf-8?


2
Non è chiaro cosa esattamente stai cercando di fare. MyString contiene correttamente il carattere ñ e hai problemi a convertirlo in un array di byte (in quel caso vedi le risposte di Peter e Amir), oppure myString è corrotto e stai cercando di risolverlo (in quel caso, vedi le risposte di Joachim e io)?
Michael Borgwardt,

Devo inviare myString a un server con codifica utf-8 e devo convertire il carattere "ñ" in codifica utf-8.
Alex,

1
Bene, se quel server si aspetta UTF-8, allora ciò che è necessario per inviarlo sono byte, non una stringa. Quindi, secondo la risposta di Peter, specifica la codifica nella prima riga e rilascia la seconda riga.
Michael Borgwardt,

@Michael: sono d'accordo che non sia chiaro quale sia il vero intento qui. Sembra che ci siano molte domande in cui le persone stanno cercando di esplicitare conversioni tra stringhe e byte piuttosto che lasciarlo {In,Out}putStream{Read,Writ}ersfare per loro. Mi chiedo perché?
tchrist,

1
@Michael: Grazie, suppongo abbia senso. Ma lo rende anche più difficile di quanto deve essere, no? Non amo molto le lingue che funzionano in questo modo, quindi cerco di evitare di lavorare con loro. Penso che il modello Java di stringhe di caratteri anziché byte renda le cose molto più facili. Perl e Python condividono anche il modello "tutto è stringhe Unicode". Sì, in tutti e tre i casi puoi ancora ottenere byte se ci lavori, ma in pratica sembra raro che tu abbia davvero bisogno: è piuttosto basso livello. Inoltre sembra un po 'come spazzolare un gatto nella direzione sbagliata, se sai cosa intendo. :)
tchrist,

Risposte:


140

String gli oggetti in Java usano la codifica UTF-16 che non può essere modificata.

L'unica cosa che può avere una codifica diversa è a byte[]. Quindi, se hai bisogno di dati UTF-8, allora hai bisogno di un byte[]. Se si dispone di un file Stringcontenente dati imprevisti, il problema si trova in un punto precedente che ha erroneamente convertito alcuni dati binari in un String(ovvero utilizzava una codifica errata).


92
Tecnicamente parlando, byte [] non ha alcuna codifica. La codifica di byte array PLUS può darti comunque una stringa.
Peter Štibraný,

1
@Peter: vero. Ma allegare una codifica ad essa ha senso byte[], non ha senso per String(a meno che la codifica sia UTF-16, nel qual caso ha senso ma è comunque un'informazione non necessaria).
Joachim Sauer,

4
String objects in Java use the UTF-16 encoding that can't be modified. Hai una fonte ufficiale per questa citazione?
Ahmad Hajjar,

@AhmadHajjar docs.oracle.com/javase/10/docs/api/java/lang/… : "La piattaforma Java utilizza la rappresentazione UTF-16 negli array di caratteri e nelle classi String e StringBuffer."
Maxi Gis,

173

Che ne dici di usare

ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(myString)

Vedi la mia discussione con Peter. Ma se il suo presupposto sulla domanda è giusto, la tua soluzione non sarebbe ancora un'idea poiché restituisce un ByteBuffer.
Michael Borgwardt,

8
Ma come posso ottenere una stringa codificata? restituisce un ByteBuffer
Alex

7
@Alex: non è possibile avere una stringa Java codificata UTF-8. Vuoi byte, quindi usa direttamente ByteBuffer (potrebbe anche essere la soluzione migliore se il tuo obiettivo è inviarlo tramite una raccolta di rete) o chiama array () su di esso per ottenere un byte []
Michael Borgwardt,

2
Qualcos'altro che può essere utile è usare l'enum Charsets.UTF_8 di Guava invece di una stringa che può generare un UnsupportedEncodingException. String -> byte: myString.getBytes(Charsets.UTF_8)e byte -> Stringa: new String(myByteArray, Charsets.UTF_8).
laughing_man

24
Ancora meglio, usa StandardCharsets.UTF_8. Disponibile in Java 1.7+.
Kat,

81

In Java7 è possibile utilizzare:

import static java.nio.charset.StandardCharsets.*;

byte[] ptext = myString.getBytes(ISO_8859_1); 
String value = new String(ptext, UTF_8); 

Ciò ha il vantaggio di getBytes(String)non essere dichiarato throws UnsupportedEncodingException.

Se stai utilizzando una versione Java precedente, puoi dichiarare tu stesso le costanti del set di caratteri:

import java.nio.charset.Charset;

public class StandardCharsets {
    public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
    public static final Charset UTF_8 = Charset.forName("UTF-8");
    //....
}

2
Questa è la risposta esatta. Se qualcuno vuole usare un tipo di dati stringa, può usarlo nel formato giusto. Il resto delle risposte punta al tipo di byte formattato.
Neeraj Shukla,

Funziona in 6. Grazie.
Itsik Mauyhas,

Risposta corretta anche per me. Una cosa però, quando ho usato come sopra, il personaggio tedesco è cambiato in?. Quindi, ho usato questo: byte [] ptext = myString.getBytes (UTF_8); Valore stringa = nuova stringa (ptext, UTF_8); Questo ha funzionato bene.
Farhan Hafeez,

3
L'esempio di codice non ha senso. Se prima converti in ISO-8859-1, quell'array di byte non è UTF-8, quindi la riga successiva è totalmente errata. Essa opererà per le stringhe ASCII, naturalmente, ma poi si potrebbe anche fare una semplice copia: String value = new String(myString);.
Alexis Wilke,

76

Usa byte[] ptext = String.getBytes("UTF-8");invece di getBytes(). getBytes()utilizza la cosiddetta "codifica predefinita", che potrebbe non essere UTF-8.


9
@Michael: sta chiaramente avendo problemi a ottenere byte dalla stringa. In che modo getBytes (codifica) manca il punto? Penso che la seconda riga sia lì solo per verificare se può riconvertirla.
Peter Štibraný,

1
Lo interpreto come avere una stringa rotta e provare a "ripararla" convertendola in byte e viceversa (malinteso comune). Non c'è alcuna indicazione effettiva che la seconda riga stia solo controllando il risultato.
Michael Borgwardt,

@Michael, no non c'è, è solo la mia interpretazione. Il tuo è semplicemente diverso.
Peter Štibraný,

1
@Peter: hai ragione, avremmo bisogno di chiarimenti da parte di Alex su cosa intende veramente. Tuttavia, non è possibile annullare il voto negativo a meno che la risposta non venga modificata ...
Michael Borgwardt,

33

Una stringa Java è sempre codificata internamente in UTF-16, ma dovresti davvero pensarci in questo modo: una codifica è un modo per tradurre tra stringhe e byte.

Quindi, se hai un problema di codifica, quando hai String, è troppo tardi per risolvere. È necessario correggere il luogo in cui si crea quella stringa da un file, DB o connessione di rete.


1
È un errore comune credere che le stringhe siano codificate internamente come UTF-16. Di solito lo sono, ma se è solo un dettaglio specifico dell'implementazione della classe String. Poiché l'archiviazione interna dei dati dei caratteri non è accessibile tramite l'API pubblica, un'implementazione String specifica può decidere di utilizzare qualsiasi altra codifica.
jarnbjo,

4
@jarnbjo: l'API afferma esplicitamente "Una stringa rappresenta una stringa nel formato UTF-16". L'uso di qualsiasi altra cosa come formato interno sarebbe altamente inefficiente e tutte le implementazioni effettive che conosco usano UTF-16 internamente. Quindi, a meno che tu non possa citarne uno che non lo fa, ti stai impegnando in una assurda pettinatura.
Michael Borgwardt,

È assurdo distinguere tra accesso pubblico e rappresentazione interna delle strutture di dati?
jarnbjo,

6
La JVM (per quanto rilevante per la VM) utilizza UTF-8 per la codifica di stringhe, ad esempio nei file di classe. L'implementazione di java.lang.String è disaccoppiata dalla JVM e potrei facilmente implementare la classe per te usando qualsiasi altra codifica per la rappresentazione interna se ciò è veramente necessario per rendersi conto che la tua risposta è errata. L'uso di UTF-16 come formato interno è nella maggior parte dei casi altamente inefficiente anche quando si tratta di consumo di memoria e non vedo perché, ad esempio, le implementazioni Java per l'hardware incorporato non ottimizzerebbero per la memoria anziché le prestazioni.
jarnbjo,

1
@jarnbjo: E ancora una volta: finché non si può dare un esempio concreto di una JVM cui standard API implementazione non utilizzare internamente qualcosa di diverso da UTF-16 per implementare le stringhe, la mia affermazione è corretta. E no, la classe String non è realmente disaccoppiata dalla JVM, a causa di cose come intern () e il pool costante.
Michael Borgwardt,

22

Puoi provare in questo modo.

byte ptext[] = myString.getBytes("ISO-8859-1"); 
String value = new String(ptext, "UTF-8"); 

1
Stavo impazzendo. Grazie per avere prima i byte in "ISO-8859-1" è stata la soluzione.
Gian Gomen,

2
Questo è sbagliato. Se la tua stringa include caratteri Unicode, la conversione in 8859-1 genererà un'eccezione o peggio ti darà una stringa non valida (forse la stringa senza quei caratteri con punto di codice 0x100 e oltre).
Alexis Wilke,

12

In un attimo ho attraversato questo problema e sono riuscito a risolverlo nel modo seguente

prima devo importare

import java.nio.charset.Charset;

Quindi ho dovuto dichiarare una costante da usare UTF-8eISO-8859-1

private static final Charset UTF_8 = Charset.forName("UTF-8");
private static final Charset ISO = Charset.forName("ISO-8859-1");

Quindi potrei usarlo nel modo seguente:

String textwithaccent="Thís ís a text with accent";
String textwithletter="Ñandú";

text1 = new String(textwithaccent.getBytes(ISO), UTF_8);
text2 = new String(textwithletter.getBytes(ISO),UTF_8);

1
soluzione perfetta
Tunde Pizzle,

9
String value = new String(myString.getBytes("UTF-8"));

e, se si desidera leggere un file di testo con codifica "ISO-8859-1":

String line;
String f = "C:\\MyPath\\MyFile.txt";
try {
    BufferedReader br = Files.newBufferedReader(Paths.get(f), Charset.forName("ISO-8859-1"));
    while ((line = br.readLine()) != null) {
        System.out.println(new String(line.getBytes("UTF-8")));
    }
} catch (IOException ex) {
    //...
}

2

Ho usato sotto il codice per codificare il carattere speciale specificando il formato di codifica.

String text = "This is an example é";
byte[] byteText = text.getBytes(Charset.forName("UTF-8"));
//To get original string from byte.
String originalString= new String(byteText , "UTF-8");

2

Una rapida guida passo-passo su come configurare la codifica di default UTB-8 di NetBeans. Di conseguenza NetBeans creerà tutti i nuovi file nella codifica UTF-8.

Guida dettagliata alla codifica predefinita di NetBeans UTF-8

  • Vai alla cartella etc nella directory di installazione di NetBeans

  • Modifica il file netbeans.conf

  • Trova la riga netbeans_default_options

  • Aggiungi -J-Dfile.encoding = UTF-8 tra virgolette all'interno di quella riga

    (esempio netbeans_default_options="-J-Dfile.encoding=UTF-8":)

  • Riavvia NetBeans

Si imposta la codifica predefinita NetBeans UTF-8.

Le netbeans_default_options possono contenere parametri aggiuntivi tra virgolette. In tal caso, aggiungere -J-Dfile.encoding = UTF-8 alla fine della stringa. Separalo con spazio dagli altri parametri.

Esempio:

netbeans_default_options = "- J-client -J-Xss128m -J-Xms256m -J-XX: PermSize = 32m -J-Dapple.laf.useScreenMenuBar = true -J-Dapple.awt.graphics.UseQuartz = true -J-Dsun. java2d.noddraw = true -J-Dsun.java2d.dpiaware = true -J-Dsun.zip.disableMemoryMapping = true -J-Dfile.encoding = UTF-8 "

ecco il link per ulteriori dettagli


0

Questo ha risolto il mio problema

    String inputText = "some text with escaped chars"
    InputStream is = new ByteArrayInputStream(inputText.getBytes("UTF-8"));
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.