Zeichensatzprobleme sind für sich genommen verwirrend und kompliziert, aber darüber hinaus müssen Sie sich die genauen Namen Ihrer Zeichensätze merken. Ist es "utf8"
? Oder "utf-8"
? Oder vielleicht "UTF-8"
? Wenn Sie im Internet nach Codebeispielen suchen, sehen Sie alle oben genannten Punkte. Warum nicht einfach Konstanten benennen und verwenden Charset.UTF8
?
java
character-encoding
serg
quelle
quelle
MessageDigest#getInstance()
übrigens weiter.Antworten:
Die einfache Antwort auf die gestellte Frage lautet, dass die verfügbaren Zeichensatzzeichenfolgen von Plattform zu Plattform variieren.
Es müssen jedoch sechs vorhanden sein, sodass Konstanten für diese vor langer Zeit erstellt werden könnten. Ich weiß nicht, warum sie es nicht waren.
JDK 1.4 hat mit der Einführung des Charset-Typs großartige Arbeit geleistet. Zu diesem Zeitpunkt hätten sie keine String-Konstanten mehr bereitstellen wollen, da das Ziel darin besteht, alle Benutzer dazu zu bringen, Charset-Instanzen zu verwenden. Warum also nicht die sechs Standard-Zeichensatzkonstanten bereitstellen? Ich habe Martin Buchholz gefragt, da er zufällig direkt neben mir sitzt, und er sagte, es gebe keinen wirklich besonders guten Grund, außer dass die Dinge zu diesem Zeitpunkt noch halbherzig waren - zu wenige JDK-APIs wurden nachgerüstet Akzeptieren Sie Charset, und von denen, die es waren, zeigten die Charset-Überladungen normalerweise etwas schlechtere Ergebnisse.
Es ist traurig, dass sie erst in JDK 1.6 endlich alles mit Charset-Überladungen ausgestattet haben. Und dass diese rückwärts gerichtete Leistungssituation immer noch besteht (der Grund dafür ist unglaublich seltsam und ich kann es nicht erklären, hängt aber mit der Sicherheit zusammen!).
Lange Rede, kurzer Sinn - definieren Sie einfach Ihre eigenen Konstanten oder verwenden Sie die Charsets-Klasse von Guava, mit der Tony the Pony verknüpft ist (obwohl diese Bibliothek noch nicht wirklich veröffentlicht wurde).
Update: Eine
StandardCharsets
Klasse befindet sich in JDK 7.quelle
String(byte bytes[], int offset, int length, Charset charset)
implementiert wird. Tatsächlich ist der Leistungstreffer beim Erstellen einer kleinen Zeichenfolge aus einem großen Byte [] überhaupt nicht trivial.Zwei Jahre später definieren die StandardCharsets von Java 7 nun Konstanten für die 6 Standardzeichensätze.
Wenn Sie nicht mit Java 5/6 arbeiten, können Sie die Charavets- Konstanten von Guava verwenden , wie von Kevin Bourrillion und Jon Skeet vorgeschlagen.
quelle
Ich würde argumentieren, dass wir es viel besser machen können ... warum sind die garantiert verfügbaren Zeichensätze nicht direkt zugänglich?
Charset.UTF8
sollte ein Verweis auf die seinCharset
, nicht der Name als Zeichenfolge. Auf diese Weise müssten wir nichtUnsupportedEncodingException
überall damit umgehen .Wohlgemerkt, ich denke auch, dass .NET eine bessere Strategie gewählt hat, indem es überall standardmäßig UTF-8 verwendet. Es wurde dann vermasselt, indem die Codierungseigenschaft "Betriebssystemstandard" einfach benannt wurde
Encoding.Default
- was in .NET selbst nicht der Standard ist :(Zurück zu Javans Zeichensatzunterstützung - warum gibt es keinen Konstruktor für
FileWriter
/FileReader
der ein benötigtCharset
? Grundsätzlich sind dies aufgrund dieser Einschränkung fast nutzlose Klassen - Sie benötigen fast immer eineInputStreamReader
um einFileInputStream
oder das Äquivalent für die Ausgabe :(Krankenschwester, Krankenschwester - wo ist meine Medizin?
EDIT: Mir fällt ein, dass dies die Frage nicht wirklich beantwortet hat. Die eigentliche Antwort lautet vermutlich entweder "niemand hat daran gedacht" oder "jemand hat gedacht, es sei eine schlechte Idee". Ich würde dringend empfehlen, dass interne Dienstprogrammklassen, die die Namen oder Zeichensätze bereitstellen, Doppelungen in der Codebasis vermeiden ... Oder Sie können einfach die verwenden, die wir bei Google verwendet haben, als diese Antwort zum ersten Mal geschrieben wurde . (Beachten Sie, dass Sie ab Java 7 nur noch verwenden würden
StandardCharsets
.)quelle
In Java 1.7
import java.nio.charset.StandardCharsets
Ex:
StandardCharsets.UTF_8
StandardCharsets.US_ASCII
quelle
Der aktuelle Status der Codierungs-API lässt zu wünschen übrig. Einige Teile der Java 6 API nicht akzeptieren ,
Charset
anstelle einer Zeichenkette (inlogging
,dom.ls
,PrintStream
, es könnte noch andere geben). Es hilft nicht, dass Codierungen unterschiedliche kanonische Namen für verschiedene Teile der Standardbibliothek haben sollen.Ich kann verstehen, wie die Dinge dahin kamen, wo sie sind; Ich bin mir nicht sicher, ob ich brillante Ideen habe, wie ich sie beheben kann.
Nebenbei...
Sie können die Namen für Suns Java 6 Implementierung sehen hier .
Für UTF-8 sind die kanonischen Werte
"UTF-8"
fürjava.nio
und"UTF8"
fürjava.lang
undjava.io
. Die einzigen Codierungen, für deren Unterstützung eine JRE erforderlich ist, sind: US-ASCII; ISO-8859-1; UTF-8; UTF-16BE; UTF-16LE; UTF-16 .quelle
Ich habe vor langer Zeit eine Utility-Klasse mit den Zeichensatzkonstanten UTF_8, ISO_8859_1 und US_ASCII definiert.
Außerdem habe ich vor einiger Zeit (2+ Jahre) einen einfachen Leistungstest zwischen
new String( byte[], Charset )
und durchgeführtnew String( byte[], String charset_name )
und festgestellt, dass die letztere Implementierung erheblich schneller ist. Wenn Sie sich den Quellcode unter der Haube ansehen, werden Sie feststellen, dass sie tatsächlich einen ganz anderen Weg einschlagen.Aus diesem Grund habe ich ein Dienstprogramm in dieselbe Klasse aufgenommen
Warum der String-Konstruktor (byte [], Charset) nicht dasselbe tut, ist mir ein Rätsel.
quelle
Charset
müssen nicht registriert werden, daher kann die Ausnahme auftreten. IIRC, es gab einige Änderungen in JDK7, um es für bekanntermaßen guteCharset
Implementierungen schneller zu machen (entfernen Sie die zusätzliche Kopie).