Codieren Sie den String in UTF-8

190

Ich habe einen String mit einem "ñ" -Zeichen und ich habe einige Probleme damit. Ich muss diesen String in UTF-8-Codierung codieren. Ich habe es auf diese Weise versucht, aber es funktioniert nicht:

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

Wie codiere ich diesen String in utf-8?

Alex
quelle
2
Es ist unklar, was genau Sie versuchen zu tun. Enthält myString das Zeichen ñ korrekt und Sie haben Probleme, es in ein Byte-Array zu konvertieren (in diesem Fall siehe Antworten von Peter und Amir), oder ist myString beschädigt und Sie versuchen, es zu beheben (in diesem Fall siehe Antworten von Joachim) und ich)?
Michael Borgwardt
Ich muss myString an einen Server mit utf-8-Codierung senden und das Zeichen "ñ" in utf-8-Codierung konvertieren.
Alex
1
Wenn dieser Server UTF-8 erwartet, müssen Sie zum Senden Bytes und keine Zeichenfolge senden. Geben Sie gemäß Peters Antwort die Codierung in der ersten Zeile an und löschen Sie die zweite Zeile.
Michael Borgwardt
@ Michael: Ich stimme zu, dass es nicht klar ist, was die wahre Absicht hier ist. Es scheint eine Menge Fragen zu geben, bei denen Leute versuchen, Konvertierungen zwischen Strings und Bytes explizit vorzunehmen, anstatt sie {In,Out}putStream{Read,Writ}ersdies für sie tun zu lassen. Ich wundere mich warum?
Tchrist
1
@ Michael: Danke, ich denke das macht Sinn. Aber es macht es auch schwieriger als es sein muss, nicht wahr? Ich mag Sprachen, die so funktionieren, nicht sehr und versuche daher, nicht mit ihnen zu arbeiten. Ich denke, Javas Modell von Zeichenfolgen anstelle von Bytes macht die Sache viel einfacher. Perl und Python teilen auch das Modell "Alles ist Unicode-Zeichenfolgen". Ja, in allen drei Fällen können Sie immer noch Bytes erhalten, wenn Sie daran arbeiten, aber in der Praxis scheint es selten, dass Sie dies wirklich müssen: Das ist ziemlich niedrig. Außerdem fühlt es sich an, als würde man eine Katze in die falsche Richtung bürsten, wenn man weiß, was ich meine. :)
tchrist

Antworten:

140

String Objekte in Java verwenden die UTF-16-Codierung, die nicht geändert werden kann.

Das einzige, was eine andere Codierung haben kann, ist a byte[]. Wenn Sie also UTF-8-Daten benötigen, benötigen Sie eine byte[]. Wenn Sie eine haben String, die unerwartete Daten enthält, liegt das Problem an einer früheren Stelle, an der einige Binärdaten fälschlicherweise in a konvertiert wurden String(dh die falsche Codierung verwendet wurde).

Joachim Sauer
quelle
92
Technisch gesehen hat Byte [] keine Codierung. Die Byte-Array-PLUS-Codierung kann Ihnen jedoch eine Zeichenfolge geben.
Peter Štibraný
1
@ Peter: wahr. Das Anhängen einer Codierung ist jedoch nur sinnvoll byte[], nicht sinnvoll String(es sei denn, die Codierung ist UTF-16. In diesem Fall ist sie sinnvoll, enthält jedoch immer noch unnötige Informationen).
Joachim Sauer
4
String objects in Java use the UTF-16 encoding that can't be modified. Haben Sie eine offizielle Quelle für dieses Zitat?
Ahmad Hajjar
@AhmadHajjar docs.oracle.com/javase/10/docs/api/java/lang/… : "Die Java-Plattform verwendet die UTF-16-Darstellung in char-Arrays sowie in den Klassen String und StringBuffer."
Maxi Gis
173

Wie wäre es mit

ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(myString)
Amir Rachum
quelle
Siehe meine Diskussion mit Peter. Aber wenn seine Annahme bezüglich der Frage richtig ist, wäre Ihre Lösung immer noch keine Idee, da sie einen ByteBuffer zurückgibt.
Michael Borgwardt
8
Aber wie erhalte ich einen codierten String? es gibt einen ByteBuffer zurück
Alex
7
@Alex: Es ist nicht möglich , einen UTF-8-codierten Java-String zu haben. Sie möchten Bytes, also verwenden Sie entweder den ByteBuffer direkt (könnte sogar die beste Lösung sein, wenn Sie ihn über eine Netzwerksammlung senden möchten) oder rufen Sie array () auf, um ein Byte [] zu erhalten
Michael Borgwardt
2
Etwas anderes, das hilfreich sein kann, ist die Verwendung der Aufzählung Charsets.UTF_8 von Guava anstelle eines Strings, der möglicherweise eine UnsupportedEncodingException auslöst. String -> Bytes: myString.getBytes(Charsets.UTF_8)und Bytes -> String : new String(myByteArray, Charsets.UTF_8).
Lachen_man
24
Noch besser verwenden StandardCharsets.UTF_8. Verfügbar in Java 1.7+.
Kat
81

In Java7 können Sie Folgendes verwenden:

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

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

Dies hat den Vorteil, getBytes(String)dass es nicht deklariert throws UnsupportedEncodingException.

Wenn Sie eine ältere Java-Version verwenden, können Sie die Zeichensatzkonstanten selbst deklarieren:

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");
    //....
}
rzymek
quelle
2
Das ist die richtige Antwort. Wenn jemand einen String-Datentyp verwenden möchte, kann er ihn im richtigen Format verwenden. Die restlichen Antworten verweisen auf den byteformatierten Typ.
Neeraj Shukla
Funktioniert in 6. Danke.
Itsik Mauyhas
Richtige Antwort auch für mich. Eines jedoch, als ich wie oben verwendet habe, hat sich der deutsche Charakter in? Geändert. Also habe ich folgendes verwendet: byte [] ptext = myString.getBytes (UTF_8); String value = neuer String (ptext, UTF_8); Das hat gut funktioniert.
Farhan Hafeez
3
Das Codebeispiel macht keinen Sinn. Wenn Sie zuerst nach ISO-8859-1 konvertieren, ist dieses Byte-Array nicht UTF-8, sodass die nächste Zeile völlig falsch ist. Es wird natürlich für ASCII-Strings funktionieren, aber dann können Sie auch eine einfache Kopie erstellen : String value = new String(myString);.
Alexis Wilke
76

Verwenden Sie byte[] ptext = String.getBytes("UTF-8");anstelle von getBytes(). getBytes()verwendet die sogenannte "Standardcodierung", die möglicherweise nicht UTF-8 ist.

Peter Štibraný
quelle
9
@ Michael: Er hat eindeutig Probleme, Bytes von der Zeichenfolge zu erhalten. Wie fehlt getBytes (Codierung) der Punkt? Ich denke, die zweite Zeile ist nur da, um zu überprüfen, ob er sie zurückkonvertieren kann.
Peter Štibraný
1
Ich interpretiere es als einen gebrochenen String und versuche, ihn durch Konvertieren in Bytes und zurück zu "reparieren" (häufiges Missverständnis). Es gibt keinen tatsächlichen Hinweis darauf, dass die zweite Zeile nur das Ergebnis überprüft.
Michael Borgwardt
@ Michael, nein, gibt es nicht, es ist nur meine Interpretation. Dein ist einfach anders.
Peter Štibraný
1
@Peter: Du hast recht, wir müssten von Alex klären, was er wirklich meint. Ich kann die Abstimmung jedoch nicht widerrufen, es sei denn, die Antwort wurde bearbeitet ...
Michael Borgwardt
33

Ein Java-String wird intern immer in UTF-16 codiert - aber Sie sollten wirklich so darüber nachdenken: Eine Codierung ist eine Möglichkeit, zwischen Strings und Bytes zu übersetzen.

Wenn Sie also ein Codierungsproblem haben, ist es zu spät, es zu beheben, wenn Sie String haben. Sie müssen den Ort festlegen, an dem Sie diesen String aus einer Datei, einer Datenbank oder einer Netzwerkverbindung erstellen.

Michael Borgwardt
quelle
1
Es ist ein häufiger Fehler zu glauben, dass Zeichenfolgen intern als UTF-16 codiert sind. Normalerweise sind sie es, aber wenn, ist es nur ein implementierungsspezifisches Detail der String-Klasse. Da der interne Speicher der Zeichendaten nicht über die öffentliche API zugänglich ist, kann eine bestimmte String-Implementierung entscheiden, eine andere Codierung zu verwenden.
jarnbjo
3
@jarnbjo: Die API gibt explizit an, dass "ein String einen String im UTF-16-Format darstellt". Die Verwendung von anderen Elementen als internes Format wäre äußerst ineffizient, und alle mir bekannten tatsächlichen Implementierungen verwenden UTF-16 intern. Wenn Sie also keine zitieren können, die dies nicht tut, beschäftigen Sie sich mit ziemlich absurdem Haarspalterei.
Michael Borgwardt
Ist es absurd, zwischen öffentlichem Zugang und interner Repräsentation von Datenstrukturen zu unterscheiden?
jarnbjo
5
Die JVM (soweit dies für die VM überhaupt relevant ist) verwendet UTF-8 für die Zeichenfolgencodierung, z. B. in den Klassendateien. Die Implementierung von java.lang.String ist von der JVM entkoppelt, und ich könnte die Klasse problemlos für Sie implementieren, indem Sie eine andere Codierung für die interne Darstellung verwenden, wenn dies wirklich erforderlich ist, damit Sie feststellen, dass Ihre Antwort falsch ist. Die Verwendung von UTF-16 als internes Format ist in den meisten Fällen auch in Bezug auf den Speicherverbrauch äußerst ineffizient, und ich verstehe nicht, warum z. B. Java-Implementierungen für eingebettete Hardware nicht für Speicher anstatt für Leistung optimiert werden.
jarnbjo
1
@jarnbjo: Und noch einmal: Solange Sie nicht ein konkretes Beispiel für eine JVM , deren Standard - API - Implementierung geben können nicht verwenden intern etwas anderes als UTF-16 Strings zu implementieren, ist meine Aussage richtig. Und nein, die String-Klasse ist aufgrund von Dingen wie intern () und dem konstanten Pool nicht wirklich von der JVM entkoppelt.
Michael Borgwardt
22

Sie können diesen Weg versuchen.

byte ptext[] = myString.getBytes("ISO-8859-1"); 
String value = new String(ptext, "UTF-8"); 
user716840
quelle
1
Ich wurde verrückt. Vielen Dank, dass Sie zuerst die Bytes in "ISO-8859-1" erhalten haben, war die Lösung.
Gian Gomen
2
Das ist falsch. Wenn Ihre Zeichenfolge Unicode-Zeichen enthält, löst die Konvertierung in 8859-1 eine Ausnahme aus oder führt zu einer ungültigen Zeichenfolge (möglicherweise die Zeichenfolge ohne diese Zeichen mit dem Codepunkt 0x100 und höher).
Alexis Wilke
12

In einem Moment ging ich dieses Problem durch und schaffte es, es auf folgende Weise zu lösen

Zuerst muss ich importieren

import java.nio.charset.Charset;

Dann musste ich eine Konstante deklarieren, um UTF-8und zu verwendenISO-8859-1

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

Dann könnte ich es folgendermaßen verwenden:

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);
Quimbo
quelle
1
perfekte Lösung.
Tunde Pizzle
9
String value = new String(myString.getBytes("UTF-8"));

und wenn Sie aus einer Textdatei mit der Codierung "ISO-8859-1" lesen möchten:

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) {
    //...
}
fedesanp
quelle
2

Ich habe den folgenden Code verwendet, um das Sonderzeichen durch Angabe des Codierungsformats zu codieren.

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");
laxman954
quelle
2

Eine kurze Schritt-für-Schritt-Anleitung zum Konfigurieren der NetBeans-Standardcodierung UTF-8. Im Ergebnis erstellt NetBeans alle neuen Dateien in UTF-8-Codierung.

Schrittweise Anleitung zur NetBeans-Standardcodierung UTF-8

  • Wechseln Sie zum Ordner etc im NetBeans-Installationsverzeichnis

  • Bearbeiten Sie die Datei netbeans.conf

  • Suchen Sie die Zeile netbeans_default_options

  • Fügen Sie -J-Dfile.encoding = UTF-8 in Anführungszeichen innerhalb dieser Zeile ein

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

  • Starten Sie NetBeans neu

Sie legen die NetBeans-Standardcodierung UTF-8 fest.

Ihre netbeans_default_options können zusätzliche Parameter in Anführungszeichen enthalten. Fügen Sie in diesem Fall am Ende der Zeichenfolge -J-Dfile.encoding = UTF-8 hinzu. Trennen Sie es mit Leerzeichen von anderen Parametern.

Beispiel:

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 "

Hier ist der Link für weitere Details

Herr Laeeq Khan
quelle
0

Dies löste mein Problem

    String inputText = "some text with escaped chars"
    InputStream is = new ByteArrayInputStream(inputText.getBytes("UTF-8"));
Prasanth RJ
quelle