Warum sind Zeichensatznamen keine Konstanten?

Lesezeit: 7 Minuten

Benutzer-Avatar
serg

Zeichensatzprobleme sind an sich 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, werden Sie alle oben genannten sehen. Warum machen Sie sie nicht einfach zu benannten Konstanten und verwenden sie Charset.UTF8?

  • +1: Das hat mich auch die ganze Zeit genervt. Die gleiche Geschichte geht weiter für MessageDigest#getInstance() übrigens.

    – BalusC

    5. November 2009 um 22:34 Uhr

  • Für die wirkliche Antwort müssten Sie jemanden bei Sun fragen. Viel Glück damit 🙂

    – Stefan C

    6. November 2009 um 5:31 Uhr

  • Stephen C: Ich glaube, es wurde auf einer öffentlichen Mailingliste diskutiert. -Jemand bei Sun.

    – Tom Hawtin – Angelleine

    6. November 2009 um 15:17 Uhr

  • siehe diese Frage

    – jegor256

    27. September 2012 um 9:16 Uhr

Benutzer-Avatar
Kevin Bourrillion

Die einfache Antwort auf die gestellte Frage lautet, dass die verfügbaren Zeichensätze von Plattform zu Plattform unterschiedlich sind.

Es gibt jedoch sechs, die vorhanden sein müssen, also hätten vor langer Zeit Konstanten für diese gemacht werden können. Ich weiß nicht, warum sie es nicht waren.

JDK 1.4 hat eine großartige Sache gemacht, indem es den Charset-Typ eingeführt hat. An diesem Punkt hätten sie keine String-Konstanten mehr bereitstellen wollen, da das Ziel darin besteht, dass jeder Charset-Instanzen verwendet. Warum also nicht die sechs Standard-Charset-Konstanten bereitstellen? Ich habe Martin Buchholz gefragt, da er zufällig neben mir sitzt, und er sagte, es gäbe keinen wirklich besonders guten Grund, außer dass damals noch alles halbgar war – zu wenige JDK-APIs wurden nachgerüstet akzeptieren Charset, und von denen, die es waren, schnitten die Charset-Überladungen normalerweise etwas schlechter ab.

Schade, dass sie erst in JDK 1.6 endlich alles mit Charset-Überladungen ausgestattet haben. Und dass diese Rückwärtsleistungssituation immer noch besteht (der Grund dafür ist unglaublich seltsam und ich kann es nicht erklären, hängt aber mit der Sicherheit zusammen!).

Um es kurz zu machen – 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).

Aktualisieren: a StandardCharsets Klasse ist in JDK 7.

  • Nur neugierig, hast du eine Ahnung, wann es eine Veröffentlichung (Alpha / Beta / was auch immer) von Guava geben wird? Die Projekt-Homepage ist diesbezüglich etwas knapp.

    – Jonik

    6. November 2009 um 2:02 Uhr

  • Kein Truthahn für mich, bis es draußen ist!

    – Kevin Bourrillion

    7. November 2009 um 4:43 Uhr

  • Der Grund dafür ist unglaublich seltsam und ich kann es nicht erklären, aber es hängt mit der Sicherheit zusammen – Sie können einen modifizierbaren String über benutzerdefinierte Zeichensätze erstellen, aber sie hätten noch schneller funktionieren können als String (der den Zeichensatz tatsächlich nachschlägt). Es ist eine Auslassung / Vernachlässigung, wie String(byte bytes[], int offset, int length, Charset charset) ist implementiert. Tatsächlich ist der Leistungseinbruch überhaupt nicht trivial, wenn aus einem großen Byte eine kleine Zeichenfolge erstellt wird[].

    – bestes

    16. Januar 2013 um 7:24 Uhr


  • Keine Messe! Sie haben Zugang zu so großartigen Ressourcen. =( Ich habe eine andere Antwort gesehen, wo du einmal gesagt hast: “Ja, also habe ich Josh gefragt [Bloch] über das…”

    – Kevinarpe

    20. Juli 2013 um 13:33 Uhr

  • PrintStream unterstützt kein Charset

    – Rofrol

    24. November 2014 um 12:35 Uhr

Benutzer-Avatar
Etienne Neveu

Zwei Jahre später und Java 7 Standardzeichensätze definiert jetzt Konstanten für die 6 Standardzeichensätze.

Wenn Sie auf Java 5/6 feststecken, können Sie Guava’s verwenden Zeichensätze Konstanten, wie von Kevin Bourrillion und Jon Skeet vorgeschlagen.

Benutzer-Avatar
Jon Skeet

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 Hinweis auf die sein Charset, nicht der Name als String. So müssten wir nicht damit umgehen UnsupportedEncodingException überall.

Wohlgemerkt, ich denke auch, dass .NET eine bessere Strategie gewählt hat, indem es standardmäßig überall auf UTF-8 gesetzt hat. Es hat es dann vermasselt, indem es die Codierungseigenschaft “Betriebssystem-Standard” einfach benannt hat Encoding.Default – die ist nicht der Standard in .NET selbst 🙁

Zurück zum Geschwätz über die Zeichensatzunterstützung von Java – warum gibt es keinen Konstruktor für FileWriter/FileReader was dauert Charset? Im Grunde genommen sind das aufgrund dieser Einschränkung fast nutzlose Klassen – Sie brauchen fast immer eine InputStreamReader um a FileInputStreamoder das Äquivalent für die Ausgabe 🙁

Krankenschwester, Krankenschwester – wo ist meine Medizin?

EDIT: Mir fällt auf, dass dies die Frage nicht wirklich beantwortet hat. Die wirkliche Antwort lautet vermutlich entweder „kein Beteiligter hat daran gedacht“ oder „jemand Beteiligter hielt es für eine schlechte Idee“. Ich würde dringend vorschlagen, dass interne Hilfsklassen, die die Namen oder Zeichensätze bereitstellen, eine Duplizierung in der Codebasis vermeiden … Oder Sie könnten einfach verwenden die, die wir bei Google verwendet haben, als diese Antwort zum ersten Mal geschrieben wurde. (Beachten Sie, dass Sie ab Java 7 einfach verwenden würden StandardCharsets stattdessen.)

  • +1. Aber als Methode und nicht als Feld, um Lazy Loading zu ermöglichen (okay, Sie werden wahrscheinlich UTF-8 wollen, aber es gibt ein paar andere Zeichensätze und Sie möchten vielleicht ähnliche Einrichtungen für sie). Leider scheint dies bei den Entscheidungsträgern nicht sehr beliebt zu sein.

    – Tom Hawtin – Angelleine

    5. November 2009 um 22:22 Uhr

  • Ich wäre mit einer Methode zufrieden, obwohl ich hoffe, dass das eifrige Laden dieser wenigen Zeichensätze keine erheblichen Kosten verursachen würde.

    – Jon Skeet

    5. November 2009 um 22:24 Uhr

  • Wir sind auf einem Kreuzzug, um das eifrige Laden von Klassen zu stoppen. / Habe gerade in einem JDK nach “UTF-8” gesucht. 270 Übereinstimmung(en) in 165 Datei(en) gefunden. Obwohl vieles davon in altem Apache-Müll steckt (ich glaube, von meinem Team beigetragen).

    – Tom Hawtin – Angelleine

    5. November 2009 um 22:33 Uhr

  • @tackline: Ich nehme an, dass eifriges Klassenladen eines dieser Dinge ist, die sich mit der Zeit anhäufen. Ein paar Klassen hier, ein paar Klassen dort – jede einzeln klingt harmlos genug – könnte einen großen Unterschied machen.

    – Jon Skeet

    5. November 2009 um 22:46 Uhr

  • Der letzte Link zu Guava Charsets ist defekt.

    – LarsH

    4. Juni 2018 um 16:30 Uhr

Bei Java 1.7

import java.nio.charset.StandardCharsets

ex:
StandardCharsets.UTF_8
StandardCharsets.US_ASCII

Der aktuelle Stand der Codierungs-API lässt zu wünschen übrig. Einige Teile der Java 6-API akzeptieren nicht Charset anstelle einer Zeichenfolge (in logging, dom.ls, PrintStream; es können noch andere sein). Es hilft nicht, dass Kodierungen für verschiedene Teile der Standardbibliothek unterschiedliche kanonische Namen haben sollen.

Ich kann verstehen, wie die Dinge dahin gekommen sind, wo sie sind; Ich bin mir nicht sicher, ob ich irgendwelche brillanten Ideen habe, wie ich sie reparieren kann.


Nebenbei…

Sie können die Namen für die Java 6-Implementierung von Sun nachschlagen hier.

Für UTF-8 sind die kanonischen Werte "UTF-8" zum java.nio und "UTF8" zum java.lang und java.io. Die einzigen Codierungen, die für die Spezifikation von einer JRE unterstützt werden müssen, sind: US-ASCII; ISO-8859-1; UTF-8; UTF-16BE; UTF-16LE; UTF-16.

  • Ich missgönne dem PrintStream nicht, da die Klasse eindeutig sagt: “Die PrintWriter-Klasse sollte in Situationen verwendet werden, in denen Zeichen statt Bytes geschrieben werden müssen.” (Was alle Situationen sind …)

    – Kevin Bourrillion

    5. November 2009 um 23:46 Uhr

Ich habe vor langer Zeit eine Utility-Klasse mit UTF_8-, ISO_8859_1- und US_ASCII-Charset-Konstanten definiert.

Außerdem habe ich vor einiger Zeit (über 2 Jahre) einen einfachen Leistungstest zwischendurch durchgeführt new String( byte[], Charset ) und new String( byte[], String charset_name ) und entdeckt, dass die letztere Implementierung ist WESENTLICH Schneller. Wenn Sie einen Blick unter die Haube des Quellcodes werfen, werden Sie sehen, dass sie tatsächlich einen ganz anderen Weg gehen.

Aus diesem Grund habe ich ein Dienstprogramm in dieselbe Klasse aufgenommen

public static String stringFromByteArray (
    final byte[] array,
    final Charset charset
)
{
    try
    {
        return new String( array, charset.name( ) )
    }
    catch ( UnsupportedEncodingException ex )
    {
        // cannot happen
    }
}

Warum die Zeichenfolge (Byte[]Charset ) Konstruktor macht nicht dasselbe, schlägt mich.

  • Ich missgönne dem PrintStream nicht, da die Klasse eindeutig sagt: “Die PrintWriter-Klasse sollte in Situationen verwendet werden, in denen Zeichen statt Bytes geschrieben werden müssen.” (Was alle Situationen sind …)

    – Kevin Bourrillion

    5. November 2009 um 23:46 Uhr

1354890cookie-checkWarum sind Zeichensatznamen keine Konstanten?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy