it-swarm.dev

Sollte UTF-16 als schädlich angesehen werden?

Ich werde fragen, was wahrscheinlich eine ziemlich kontroverse Frage ist: "Sollte eine der beliebtesten Codierungen, UTF-16, als schädlich angesehen werden?"

Warum stelle ich diese Frage?

Wie vielen Programmierern ist bekannt, dass UTF-16 tatsächlich eine Codierung mit variabler Länge ist? Damit meine ich, dass es Codepunkte gibt, die als Ersatzpaare dargestellt mehr als ein Element annehmen.

Ich kenne; Viele Anwendungen, Frameworks und APIs verwenden UTF-16, wie Java-String, C # -String, Win32-APIs, Qt-GUI-Bibliotheken, die ICU Unicode-Bibliothek usw.). Es gibt viele grundlegende Fehler bei der Verarbeitung von Zeichen aus BMP (Zeichen, die mit zwei UTF-16-Elementen codiert werden sollten).

Versuchen Sie beispielsweise, eines dieser Zeichen zu bearbeiten:

  • ???? ( + 1D11E ) MUSICAL SYMBOL G CLEF
  • ???? ( + 1D565 ) MATHEMATISCHES DOPPELSTRUCK SMALL T
  • ???? ( + 1D7F6 ) MATHEMATISCHE MONOSPACE DIGIT ZERO
  • ???? ( + 2008A ) Han-Zeichen

Je nachdem, welche Schriftarten Sie installiert haben, fehlen möglicherweise einige. Diese Zeichen befinden sich alle außerhalb der BMP (Mehrsprachige Grundebene). Wenn Sie diese Zeichen nicht sehen können, können Sie sie auch in der nicode-Zeichenreferenz anzeigen.

Versuchen Sie beispielsweise, in Windows Dateinamen zu erstellen, die diese Zeichen enthalten. Versuchen Sie, diese Zeichen mit einer "Rücktaste" zu löschen, um zu sehen, wie sie sich in verschiedenen Anwendungen verhalten, die UTF-16 verwenden. Ich habe einige Tests gemacht und die Ergebnisse sind ziemlich schlecht:

  • Opera hat Probleme beim Bearbeiten (Löschen der erforderlichen 2 Drücken auf der Rücktaste)
  • Notepad kann nicht richtig damit umgehen (Löschen erforderlich 2 Drücken auf die Rücktaste)
  • Dateinamen, die in Fensterdialogen bearbeitet werden, sind defekt (Löschen erforderlich 2 Drücken auf die Rücktaste)
  • Alle QT3-Anwendungen können nicht mit ihnen umgehen - zeigen zwei leere Quadrate anstelle eines Symbols.
  • Python codiert solche Zeichen falsch, wenn es auf einigen Plattformen direkt u'X'!=unicode('X','utf-16') verwendet wird, wenn X Zeichen außerhalb von BMP enthält.
  • Python 2.5-Unicodedata können keine Eigenschaften für solche Zeichen abrufen, wenn python mit UTF-16-Unicode-Zeichenfolgen kompiliert wurde.
  • StackOverflow scheint diese Zeichen aus dem Text zu entfernen, wenn sie direkt als Unicode-Zeichen bearbeitet werden (diese Zeichen werden mit HTML-Unicode-Escapezeichen angezeigt).
  • WinForms TextBox kann eine ungültige Zeichenfolge generieren wenn mit MaxLength begrenzt.

Es scheint, dass solche Fehler in vielen Anwendungen, die UTF-16 verwenden, extrem leicht zu finden sind.

Also ... Denkst du, dass UTF-16 als schädlich angesehen werden sollte?

432
Artyom

Dies ist eine alte Antwort.
Die neuesten Updates finden Sie unter TF-8 Everywhere .

Meinung: Ja, UTF-16 sollte als schädlich angesehen werden . Der Grund dafür ist, dass es vor einiger Zeit eine falsche Überzeugung gab, dass Widechar das sein wird, was UCS-4 jetzt ist.

Trotz des "Anglozentrismus" von UTF-8 sollte es als die einzige nützliche Codierung für Text angesehen werden. Man kann argumentieren, dass Quellcodes von Programmen, Webseiten und XML-Dateien, Betriebssystemdateinamen und anderen Computer-zu-Computer-Textschnittstellen niemals existieren sollten. Aber wenn sie es tun, ist Text nicht nur für menschliche Leser.

Auf der anderen Seite ist UTF-8-Overhead ein geringer Preis, der erhebliche Vorteile bietet. Vorteile wie die Kompatibilität mit nicht bekanntem Code, der nur Zeichenfolgen mit char* Übergibt. Das ist eine großartige Sache. Es gibt nur wenige nützliche Zeichen, die in UTF-16 KURZER sind als in UTF-8.

Ich glaube, dass alle anderen Kodierungen irgendwann sterben werden. Dies beinhaltet, dass MS-Windows, Java, ICU, python aufhören, es als ihren Favoriten zu verwenden. Nach langen Recherchen und Diskussionen verbieten die Entwicklungskonventionen bei meine Firma die Verwendung von UTF -16 überall außer OS-API-Aufrufen, und dies trotz der Bedeutung der Leistung in unseren Anwendungen und der Tatsache, dass wir Windows verwenden. Konvertierungsfunktionen wurden entwickelt, um immer angenommene UTF8 std::string In native UTF-16 zu konvertieren Windows selbst nterstützt nicht richtig .

Für Leute, die sagen " verwenden, was benötigt wird, wo es benötigt wird", sage ich: Es ist ein großer Vorteil, überall dieselbe Codierung zu verwenden, und ich sehe keinen ausreichenden Grund, etwas anderes zu tun. Insbesondere denke ich, dass das Hinzufügen von wchar_t Zu C++ ein Fehler war, ebenso wie die Unicode-Ergänzungen zu C++ 0x. Was jedoch von STL-Implementierungen verlangt werden muss, ist, dass jeder std::string Oder char* Parameter als Unicode-kompatibel angesehen wird.

Ich bin auch gegen den Ansatz " benutze was du willst". Ich sehe keinen Grund für eine solche Freiheit. Es gibt genug Verwirrung beim Thema Text, was zu all dieser kaputten Software führt. Trotzdem bin ich überzeugt, dass Programmierer endlich einen Konsens über UTF-8 als einen richtigen Weg erzielen müssen. (Ich komme aus einem nicht ASCII-sprechenden Land und bin mit Windows aufgewachsen. Es wird also zuletzt erwartet, dass ich UTF-16 aus religiösen Gründen angreife.).

Ich möchte weitere Informationen darüber teilen, wie ich Text unter Windows erstelle und was ich allen anderen empfehle, um die Unicode-Korrektheit, Benutzerfreundlichkeit und bessere Multi-Plattform-Funktionalität des Codes zur Kompilierungszeit zu überprüfen. Der Vorschlag unterscheidet sich erheblich von dem, was normalerweise als die richtige Art der Verwendung von Unicode unter Windows empfohlen wird. Eine eingehende Untersuchung dieser Empfehlungen ergab jedoch die gleiche Schlussfolgerung. Also los geht's:

  • Verwenden Sie wchar_t Oder std::wstring Nicht an einem anderen Ort als dem angrenzenden Punkt zu APIs, die UTF-16 akzeptieren.
  • Verwenden Sie keine _T("") oder L"" UTF-16-Literale (Diese sollten IMO als Teil der UTF-16-Ablehnung aus dem Standard entfernt werden).
  • Verwenden Sie keine Typen, Funktionen oder deren Ableitungen, die für die Konstante _UNICODE Empfindlich sind, wie z. B. LPTSTR oder CreateWindow().
  • _UNICODE Wurde jedoch immer definiert, um zu vermeiden, dass char* - Zeichenfolgen an WinAPI übergeben werden, die stillschweigend kompiliert werden
  • std::strings Und char* An einer beliebigen Stelle im Programm gelten als UTF-8 (sofern nicht anders angegeben).
  • Alle meine Zeichenfolgen sind std::string, Obwohl Sie char * oder Zeichenfolgenliteral an convert(const std::string &) übergeben können.
  • verwenden Sie nur Win32-Funktionen, die Widechars akzeptieren (LPWSTR). Niemals diejenigen, die LPTSTR oder LPSTR akzeptieren. Übergeben Sie die Parameter folgendermaßen:

    ::SetWindowTextW(Utils::convert(someStdString or "string litteral").c_str())
    

    (Die Richtlinie verwendet die folgenden Konvertierungsfunktionen.)

  • Mit MFC-Strings:

    CString someoneElse; // something that arrived from MFC. Converted as soon as possible, before passing any further away from the API call:
    
    std::string s = str(boost::format("Hello %s\n") % Convert(someoneElse));
    AfxMessageBox(MfcUtils::Convert(s), _T("Error"), MB_OK);
    
  • Arbeiten mit Dateien, Dateinamen und Fstream unter Windows:

    • Übergeben Sie niemals die Dateinamenargumente std::string Oder const char* An die Familie fstream. MSVC STL unterstützt keine UTF-8-Argumente, verfügt jedoch über eine nicht standardmäßige Erweiterung, die wie folgt verwendet werden sollte:
    • Konvertieren Sie std::string Argumente mit std::wstring In Utils::Convert:

      std::ifstream ifs(Utils::Convert("hello"),
                        std::ios_base::in |
                        std::ios_base::binary);
      

      Wir müssen die Konvertierung manuell entfernen, wenn sich die Einstellung von MSVC zu fstream ändert.

    • Dieser Code ist nicht plattformübergreifend und muss möglicherweise in Zukunft manuell geändert werden
    • Weitere Informationen finden Sie unter fstream Unicode-Forschungs-/Diskussionsfall 4215.
    • Erstellen Sie niemals Textausgabedateien mit Nicht-UTF8-Inhalten
    • Vermeiden Sie die Verwendung von fopen() aus RAII/OOD-Gründen. Verwenden Sie bei Bedarf die obigen Konventionen _wfopen() und WinAPI.

// For interface to win32 API functions
std::string convert(const std::wstring& str, unsigned int codePage /*= CP_UTF8*/)
{
    // Ask me for implementation..
    ...
}

std::wstring convert(const std::string& str, unsigned int codePage /*= CP_UTF8*/)
{
    // Ask me for implementation..
    ...
}

// Interface to MFC
std::string convert(const CString &mfcString)
{
#ifdef UNICODE
    return Utils::convert(std::wstring(mfcString.GetString()));
#else
    return mfcString.GetString();   // This branch is deprecated.
#endif
}

CString convert(const std::string &s)
{
#ifdef UNICODE
    return CString(Utils::convert(s).c_str());
#else
    Exceptions::Assert(false, "Unicode policy violation. See W569"); // This branch is deprecated as it does not support unicode
    return s.c_str();   
#endif
}
340

nicode-Codepunkte sind keine Zeichen! Manchmal sind sie nicht einmal Glyphen (visuelle Formen).

Einige Beispiele:

  • Codepunkte mit römischen Zahlen wie "ⅲ". (Ein einzelnes Zeichen, das wie "iii" aussieht.)
  • Akzentzeichen wie "á", die entweder als einzelnes kombiniertes Zeichen "\ u00e1" oder als Zeichen und getrenntes diakritisches "\ u0061\u0301" dargestellt werden können.
  • Zeichen wie das griechische Sigma in Kleinbuchstaben, die unterschiedliche Formen für die Mitte ("σ") und das Ende ("ς") der Wortpositionen haben, aber als Synonyme für die Suche betrachtet werden sollten.
  • Unicode-Bindestrich U + 00AD, der je nach Kontext möglicherweise visuell angezeigt wird oder nicht und der für die semantische Suche ignoriert wird.

Die einzige Möglichkeit, die Unicode-Bearbeitung richtig zu gestalten, besteht darin, eine von einem Experten geschriebene Bibliothek zu verwenden oder Experte zu werden und selbst eine zu schreiben. Wenn Sie nur Codepunkte zählen, leben Sie in einem Zustand der Sünde.

157
Daniel Newby

Es gibt eine einfache Faustregel für die Verwendung von UTF (Unicode Transformation Form): - utf-8 für Speicherung und Kommunikation - utf-16 für die Datenverarbeitung - Sie können sich für utf-32 entscheiden, wenn der größte Teil der von Ihnen verwendeten Plattform-API verwendet wird utf-32 (in der UNIX-Welt üblich).

Die meisten Systeme verwenden heute utf-16 (Windows, Mac OS, Java, .NET, ICU, Qt). Siehe auch dieses Dokument: http://unicode.org/notes/tn12/

Zurück zu "UTF-16 als schädlich" würde ich sagen: definitiv nicht.

Menschen, die Angst vor Ersatzzeichen haben (weil sie glauben, Unicode in eine Codierung variabler Länge umzuwandeln), verstehen die anderen (viel größeren) Komplexitäten nicht, die die Zuordnung zwischen Zeichen und einem Unicode-Codepunkt sehr komplex machen: das Kombinieren von Zeichen, Ligaturen und Variationsselektoren , Steuerzeichen usw.

Lesen Sie diese Serie einfach hier http://www.siao2.com/2009/06/29/9800913.aspx und sehen Sie, wie UTF-16 zu einem einfachen Problem wird.

54
Mihai Nita

Ja absolut.

Warum? Es hat mit Ausübungscode zu tun.

Wenn Sie sich diese Codepoint-Nutzungsstatistik auf einem großen Korpus von Tom Christiansen ansehen, werden Sie sehen, dass trans-8bit BMP Codepoints werden um mehrere Ordnungen verwendet, wenn die Größe größer als nicht ist -BMP-Codepunkte:

 2663710 U+002013 ‹–›  GC=Pd    EN DASH
 1065594 U+0000A0 ‹ ›  GC=Zs    NO-BREAK SPACE
 1009762 U+0000B1 ‹±›  GC=Sm    PLUS-MINUS SIGN
  784139 U+002212 ‹−›  GC=Sm    MINUS SIGN
  602377 U+002003 ‹ ›  GC=Zs    EM SPACE

 544 U+01D49E ‹????›  GC=Lu    MATHEMATICAL SCRIPT CAPITAL C
 450 U+01D4AF ‹????›  GC=Lu    MATHEMATICAL SCRIPT CAPITAL T
 385 U+01D4AE ‹????›  GC=Lu    MATHEMATICAL SCRIPT CAPITAL S
 292 U+01D49F ‹????›  GC=Lu    MATHEMATICAL SCRIPT CAPITAL D
 285 U+01D4B3 ‹????›  GC=Lu    MATHEMATICAL SCRIPT CAPITAL X

Nehmen Sie das TDD-Sprichwort: "Nicht getesteter Code ist fehlerhafter Code" und formulieren Sie ihn als "nicht ausgeübter Code ist fehlerhafter Code" um und überlegen Sie, wie oft Programmierer mit Nicht-BMP-Codepunkten umgehen müssen.

Fehler, die damit zusammenhängen, dass UTF-16 nicht als Codierung mit variabler Breite behandelt wird, bleiben viel häufiger unbemerkt als die entsprechenden Fehler in UTF-8 . Einige Programmiersprachen garantieren immer noch nicht, dass Sie UTF-16 anstelle von UCS-2 erhalten, und einige sogenannte Programmiersprachen auf hoher Ebene bieten Zugriff auf Codeeinheiten anstelle von Codepunkten (sogar C soll Ihnen Zugriff gewähren Codepunkte, wenn Sie wchar_t verwenden, unabhängig davon, was einige Plattformen tun).

43
ninjalj

Ich würde vorschlagen, dass das Denken, dass UTF-16 als schädlich angesehen werden könnte, besagt, dass Sie ein besseres Verständnis von Unicode erlangen müssen.

Lassen Sie mich näher darauf eingehen, da ich für die Darstellung meiner Meinung zu einer subjektiven Frage abgelehnt wurde. Was genau stört Sie an UTF-16? Würden Sie es vorziehen, wenn alles in UTF-8 codiert wäre? UTF-7? Oder wie wäre es mit UCS-4? Natürlich sind bestimmte Anwendungen nicht dafür ausgelegt, jeden einzelnen Zeichencode zu verarbeiten - aber sie sind insbesondere im heutigen globalen Informationsbereich für die Kommunikation zwischen internationalen Grenzen erforderlich.

Aber wirklich, wenn Sie der Meinung sind, dass UTF-16 als schädlich angesehen werden sollte, weil es verwirrend ist oder nicht ordnungsgemäß implementiert werden kann (Unicode kann es sicherlich sein), welche Methode der Zeichenkodierung wird dann als nicht schädlich angesehen?

EDIT: Zur Verdeutlichung: Warum sollten unsachgemäße Implementierungen eines Standards die Qualität des Standards selbst widerspiegeln? Wie andere später festgestellt haben, bedeutet dies nicht, dass das Werkzeug selbst defekt ist, nur weil eine Anwendung ein Werkzeug unangemessen verwendet. Wenn dies der Fall wäre, könnten wir wahrscheinlich Dinge wie "var-Schlüsselwort als schädlich" oder "Threading als schädlich" sagen. Ich denke, die Frage verwechselt die Qualität und die Art des Standards mit den Schwierigkeiten, die viele Programmierer bei der Implementierung und ordnungsgemäßen Verwendung haben. Ich bin der Meinung, dass dies eher auf ihr mangelndes Verständnis der Funktionsweise von Unicode als auf Unicode selbst zurückzuführen ist.

40
patjbs

An der Utf-16-Codierung ist nichts auszusetzen. Aber Sprachen, die die 16-Bit-Einheiten als Zeichen behandeln, sollten wahrscheinlich als schlecht gestaltet angesehen werden. Es ist ziemlich verwirrend, einen Typ namens 'char' zu haben, der nicht immer ein Zeichen darstellt. Da die meisten Entwickler erwarten, dass ein Zeichentyp einen Codepunkt oder ein Zeichen darstellt, wird wahrscheinlich viel Code beschädigt, wenn er Zeichen außerhalb von BMP ausgesetzt wird.

Beachten Sie jedoch, dass selbst die Verwendung von utf-32 nicht bedeutet, dass jeder 32-Bit-Codepunkt immer ein Zeichen darstellt. Aufgrund der Kombination von Zeichen kann ein tatsächliches Zeichen aus mehreren Codepunkten bestehen. Unicode ist niemals trivial.

Übrigens. Es gibt wahrscheinlich dieselbe Klasse von Fehlern bei Plattformen und Anwendungen, bei denen 8-Bit-Zeichen erwartet werden, denen Utf-8 zugeführt wird.

37
JacquesB

Meine persönliche Wahl ist es, immer UTF-8 zu verwenden. Es ist der Standard unter Linux für fast alles. Es ist abwärtskompatibel mit vielen älteren Apps. Der zusätzliche Speicherplatz für nicht-lateinische Zeichen ist im Vergleich zu den anderen UTF-Formaten sehr gering und der Platzbedarf für lateinische Zeichen ist erheblich. Im Internet herrschen lateinische Sprachen vor, und ich denke, sie werden es auf absehbare Zeit tun. Und um eines der Hauptargumente im ursprünglichen Beitrag anzusprechen: Fast jeder Programmierer ist sich bewusst, dass UTF-8 manchmal Multi-Byte-Zeichen enthält. Nicht jeder geht richtig damit um, aber er ist sich normalerweise bewusst, was mehr ist, als für UTF-16 gesagt werden kann. Aber natürlich müssen Sie diejenige auswählen, die für Ihre Anwendung am besten geeignet ist. Deshalb gibt es überhaupt mehr als eine.

20
rmeador

Nun, es gibt eine Codierung, die Symbole mit fester Größe verwendet. Ich meine auf jeden Fall UTF-32. Aber 4 Bytes für jedes Symbol sind auch viel verschwendeter Speicherplatz. Warum sollten wir ihn in alltäglichen Situationen verwenden?

Meiner Meinung nach ergeben sich die meisten Probleme aus der Tatsache, dass einige Softwareprodukte hinter dem Unicode-Standard zurückblieben, die Situation jedoch nicht schnell korrigierten. Opera, Windows, Python, Qt - alle erschienen, bevor UTF-16 allgemein bekannt wurde oder sogar entstand. Ich kann jedoch bestätigen, dass es in Opera, Windows Explorer und Notepad keine Probleme mit Zeichen außerhalb von BMP mehr) gibt (zumindest auf meinem PC). Aber trotzdem, wenn Programme nicht erkennen Ersatzpaare, dann verwenden sie kein UTF-16. Unabhängig davon, welche Probleme sich aus dem Umgang mit solchen Programmen ergeben, haben sie nichts mit UTF-16 selbst zu tun.

Ich denke jedoch, dass die Probleme von Legacy-Software mit nur BMP Unterstützung) etwas übertrieben sind. Zeichen außerhalb von BMP treten nur in ganz bestimmten Fällen und Bereichen auf zu den offiziellen Unicode-FAQ , "selbst in ostasiatischen Texten sollte die Häufigkeit von Ersatzpaaren im Durchschnitt deutlich unter 1% der gesamten Textspeicherung liegen". Natürlich Zeichen außerhalb BMP sollte nicht vernachlässigt werden, da ein Programm ansonsten nicht Unicode-konform ist, die meisten Programme jedoch nicht für die Arbeit mit Texten vorgesehen sind, die solche Zeichen enthalten unterstütze es, es ist unangenehm, aber keine Katastrophe.

Betrachten wir nun die Alternative. Wenn UTF-16 nicht vorhanden wäre, hätten wir keine Codierung, die für Nicht-ASCII-Text gut geeignet ist, und die gesamte für UCS-2 erstellte Software müsste vollständig neu gestaltet werden, um Unicode-kompatibel zu bleiben. Letzteres würde höchstwahrscheinlich nur die Einführung von Unicode verlangsamen. Außerdem wären wir nicht in der Lage gewesen, die Kompatibilität mit Text in UCS-2 aufrechtzuerhalten, wie dies UTF-8 in Bezug auf ASCII tut.

Was sind nun die Argumente gegen die Kodierung selbst, wenn man alle alten Probleme beiseite lässt? Ich bezweifle wirklich, dass Entwickler heutzutage nicht wissen, dass UTF-16 eine variable Länge hat. Es wird überall mit Wikipedia geschrieben. UTF-16 ist viel weniger schwer zu analysieren als UTF-8, wenn jemand auf Komplexität als mögliches Problem hingewiesen hat. Es ist auch falsch zu glauben, dass es leicht ist, die Stringlänge nur in UTF-16 zu bestimmen. Wenn Sie UTF-8 oder UTF-32 verwenden, sollten Sie sich dennoch bewusst sein, dass ein Unicode-Codepunkt nicht unbedingt ein Zeichen bedeutet. Abgesehen davon glaube ich nicht, dass die Kodierung wesentlich ist.

Daher denke ich nicht, dass die Codierung selbst als schädlich angesehen werden sollte. UTF-16 ist ein Kompromiss zwischen Einfachheit und Kompaktheit, und es schadet nicht, wenn verwendet wird, was benötigt wird, wo es benötigt wird . In einigen Fällen müssen Sie mit ASCII] kompatibel bleiben, und Sie benötigen UTF-8. In einigen Fällen möchten Sie mit Han-Ideogrammen arbeiten und mit UTF-16 Platz sparen, in einigen Fällen auch benötigen universelle Darstellungen von Zeichen, die eine Codierung mit fester Länge verwenden. Verwenden Sie das, was angemessener ist, und machen Sie es einfach richtig.

18
Malcolm

Die jahrelange Internationalisierungsarbeit von Windows, insbesondere in ostasiatischen Sprachen, hat mich möglicherweise korrumpiert, aber ich neige zu UTF-16 für programminterne Darstellungen von Zeichenfolgen und UTF-8 für die Netzwerk- oder Dateispeicherung von Klartext-ähnlichen Dokumenten. UTF-16 kann jedoch normalerweise unter Windows schneller verarbeitet werden. Dies ist der Hauptvorteil der Verwendung von UTF-16 unter Windows.

Durch den Sprung zu UTF-16 wurde die Angemessenheit durchschnittlicher Produkte, die internationalen Text verarbeiten, erheblich verbessert. Es gibt nur wenige enge Fälle, in denen die Ersatzpaare berücksichtigt werden müssen (Löschungen, Einfügungen und Zeilenumbrüche im Grunde), und der Durchschnittsfall ist meistens ein gerader Durchgang. Und im Gegensatz zu früheren Codierungen wie JIS-Varianten beschränkt UTF-16 Ersatzpaare auf einen sehr engen Bereich, sodass die Überprüfung sehr schnell erfolgt und vorwärts und rückwärts funktioniert.

Zugegeben, es ist auch in korrekt codiertem UTF-8 ungefähr so ​​schnell. Es gibt aber auch viele fehlerhafte UTF-8-Anwendungen, die Ersatzpaare fälschlicherweise als zwei UTF-8-Sequenzen codieren. UTF-8 garantiert also auch keine Erlösung.

IE verarbeitet Ersatzpaare seit etwa 2000 recht gut, obwohl es sie normalerweise von UTF-8-Seiten in eine interne UTF-16-Darstellung konvertiert. Ich bin mir ziemlich sicher, dass Firefox es auch richtig gemacht hat, daher ist es mir egal, was Opera] tut.

UTF-32 (auch bekannt als UCS4) ist für die meisten Anwendungen sinnlos, da es so platzsparend ist, dass es so ziemlich ein Nichtstarter ist.

16
JasonTrue

UTF-8 ist definitiv der richtige Weg, möglicherweise begleitet von UTF-32 für den internen Gebrauch in Algorithmen, die einen Hochleistungs-Direktzugriff benötigen (aber das Kombinieren von Zeichen ignorieren).

Sowohl UTF-16 als auch UTF-32 (sowie ihre LE/BE-Varianten) leiden unter Endianess-Problemen, daher sollten sie niemals extern verwendet werden.

16
Tronic

UTF-16? definitiv schädlich. Nur mein Salzkorn hier, aber es gibt genau drei akzeptable Codierungen für Text in einem Programm:

  • ASCII: Wenn es um Dinge auf niedriger Ebene geht (z. B. Mikrocontroller), die sich nichts Besseres leisten können
  • UTF8: Speicherung auf Medien mit fester Breite, z. B. Dateien
  • integer-Codepunkte ("CP"?): Ein Array der größten Ganzzahlen, die für Ihre Programmiersprache und Plattform geeignet sind (Zerfall auf ASCII im Grenzbereich niedriger Resorces). Sollte bei älteren Versionen int32 sein Computer und int64 auf alles mit 64-Bit-Adressierung.

  • Offensichtlich verwenden Schnittstellen zu Legacy-Code die Codierung, die erforderlich ist, damit der alte Code richtig funktioniert.

15
David X

nicode definiert Codepunkte bis zu 0x10FFFF (1.114.112 Codes). Alle Anwendungen, die in einer mehrsprachigen Umgebung mit Zeichenfolgen/Dateinamen usw. ausgeführt werden, sollten dies korrekt verarbeiten.

tf-16: deckt nur 1.112.064 Codes ab. Obwohl die am Ende von nicode aus den Flugzeugen 15-16 (Private Use Area) stammen. Es kann in Zukunft nicht weiter wachsen, außer das Konzept tf-16 zu brechen.

tf-8: deckt theoretisch 2.216.757.376 Codes ab. Der aktuelle Bereich von nicode Codes kann durch eine maximale 4-Byte-Sequenz dargestellt werden. Es leidet nicht unter Bytereihenfolge Problem, es ist "kompatibel" mit ASCII.

tf-32: deckt theoretisch 2 ^ 32 = 4.294.967.296 Codes ab. Derzeit ist es nicht mit variabler Länge codiert und wird es wahrscheinlich auch in Zukunft nicht sein.

Diese Tatsachen sind selbsterklärend. Ich verstehe es nicht, die allgemeine Verwendung von tf-16 zu befürworten. Es ist variabel längencodiert (kann nicht über den Index aufgerufen werden), es hat Probleme, den gesamten nicode Bereich abzudecken, auch wenn derzeit die Bytereihenfolge behandelt werden muss usw. Ich sehe keinen Vorteil, außer dass dies der Fall ist wird nativ in Windows und einigen anderen Orten verwendet. Auch wenn es beim Schreiben von Code für mehrere Plattformen wahrscheinlich besser ist, tf-8 nativ zu verwenden und Konvertierungen nur an den Endpunkten plattformabhängig durchzuführen (wie bereits vorgeschlagen). Wenn ein direkter Zugriff per Index erforderlich ist und der Speicher kein Problem darstellt, sollte tf-32 verwendet werden.

Das Hauptproblem ist, dass viele Programmierer, die sich mit Windows Unicode = tf-16 befassen, nicht einmal wissen oder ignorieren, dass es mit variabler Länge codiert ist.

Die Art und Weise, wie es normalerweise in der * nix Plattform ist, ist ziemlich gut, c Strings (char *) interpretiert als tf-8 codierte, breite c Strings (wchar_t *) interpretiert als - tf-32.

13
Pavel Machyniak

Fügen Sie dies der Liste hinzu:

Das vorgestellte Szenario ist einfach (noch einfacher, als ich es hier vorstellen werde als ursprünglich!): 1. Eine WinForms-Textbox befindet sich in einem leeren Formular. Die maximale Länge ist auf 20 festgelegt.

2. Der Benutzer gibt das Textfeld ein oder fügt möglicherweise Text ein.

3. Egal, was Sie eingeben oder in die TextBox einfügen, Sie sind auf 20 beschränkt, obwohl es bei Text jenseits der 20 mitfühlend piept (YMMV hier; ich habe mein Soundschema geändert, um diesen Effekt zu erzielen!).

4.Das kleine Textpaket wird dann an einen anderen Ort gesendet, um ein aufregendes Abenteuer zu beginnen.

Dies ist ein einfaches Szenario, und jeder kann es in seiner Freizeit aufschreiben. Ich habe es gerade selbst in mehreren Programmiersprachen mit WinForms geschrieben, weil ich gelangweilt war und es noch nie zuvor ausprobiert hatte. Und mit Text in mehreren tatsächlichen Sprachen, weil ich so verkabelt bin und mehr Tastaturlayouts habe als möglicherweise jeder andere im gesamten verdammten Universum.

Ich habe sogar die Form Magic Carpet Ride genannt, um die Langeweile zu lindern.

Das hat nicht funktioniert, was es wert ist.

Also habe ich stattdessen die folgenden 20 Zeichen in meine Magic Carpet Ride eingegeben. bilden:

0123401234012340123 ????

Oh oh.

Dieser letzte Charakter ist U + 20000, das erste Extension B-Ideogramm von Unicode (auch bekannt als U + d840 U + dc00, für seine engen Freunde, vor denen er sich nicht schämt, sozusagen vor ihm entkleidet zu werden) ....

enter image description here

Und jetzt haben wir ein Ballspiel.

Denn wenn TextBox.MaxLength darüber spricht

Ruft die maximale Anzahl von Zeichen ab oder legt diese fest, die manuell in das Textfeld eingegeben werden können.

was es wirklich bedeutet ist

Ruft die maximale Anzahl von UTF-16 LE-Codeeinheiten ab oder legt diese fest, die manuell in das Textfeld eingegeben werden können, und schneidet den lebenden Mist aus jeder Zeichenfolge, die zu spielen versucht, gnadenlos ab niedliche Spiele mit der sprachlichen Vorstellung, dass nur jemand, der so besessen ist wie dieser Kaplan-Typ, beleidigend sein wird (meine Güte, er muss mehr raus!).

Ich werde versuchen, das Dokument zu aktualisieren ...
Regelmäßige Leser, die sich an meine CS-2 bis UTF-16 -Serie erinnern, werden feststellen, dass ich mit dem simplen Begriff TextBox.MaxLength nicht zufrieden bin und wie er damit umgehen soll Zumindest in diesem Fall, in dem sein drakonisches Verhalten eine unzulässige Sequenz erzeugt, die andere Teile des .Net Frameworks möglicherweise auslösen

  • System.Text.EncoderFallbackException: Unicode-Zeichen\uD850 bei Index 0 kann nicht in die angegebene Codepage übersetzt werden. *

ausnahme, wenn Sie diese Zeichenfolge an einer anderen Stelle im .Net Framework übergeben (wie es mein Kollege Dan Thompson getan hat).

Nun okay, vielleicht ist die vollständige CS-2 bis UTF-16-Serie für viele unerreichbar.
Aber ist es nicht vernünftig zu erwarten, dass TextBox.Text kein System.String erzeugt, das nicht dazu führt, dass ein weiteres Teil des .Net Frameworks ausgelöst wird? Ich meine, es ist nicht so, dass es eine Chance in Form eines Ereignisses auf dem Steuerelement gibt, das Sie über die bevorstehende Kürzung informiert, bei der Sie einfach die intelligentere Validierung hinzufügen können - eine Validierung, die dem Steuerelement selbst nichts ausmacht. Ich würde sogar sagen, dass diese Punk-Kontrolle einen Sicherheitsvertrag bricht, der sogar zu Sicherheitsproblemen führen kann, wenn Sie unerwartete Ausnahmen zum Beenden einer Anwendung als grobe Art von Denial-of-Service klassifizieren können. Warum sollte ein WinForms-Prozess oder eine WinForms-Methode oder ein Algorithmus oder eine Technik zu ungültigen Ergebnissen führen?

Quelle: Michael S. Kaplan MSDN-Blog

11
Yuhong Bao

Ich würde nicht unbedingt sagen, dass UTF-16 schädlich ist. Es ist nicht elegant, aber es erfüllt den Zweck der Abwärtskompatibilität mit UCS-2, genau wie GB18030 mit GB2312 und UTF-8 mit ASCII.

Eine grundlegende Änderung der Struktur von Unicode im Midstream vorzunehmen, nachdem Microsoft und Sun riesige APIs mit 16-Bit-Zeichen erstellt hatten, war jedoch schädlich. Das Versäumnis, das Bewusstsein für die Veränderung zu verbreiten, war mehr schädlich.

9
dan04

Da ich noch keinen Kommentar abgeben kann, poste ich dies als Antwort, da ich anscheinend die Autoren von utf8everywhere.org Nicht anderweitig kontaktieren kann. Es ist eine Schande, dass ich nicht automatisch das Kommentarprivileg erhalte, da ich bei anderen Stapelbörsen genügend Ruf habe.

Dies ist als Kommentar zur Meinung: Ja, UTF-16 sollte als schädlich angesehen werden Antwort gedacht.

Eine kleine Korrektur:

Um zu verhindern, dass ein UTF-8 char* Versehentlich an ANSI-String-Versionen von Windows-API-Funktionen übergeben wird, sollte UNICODE definiert werden, nicht _UNICODE. _UNICODE Ordnet Funktionen wie _tcslenwcslen zu, nicht MessageBoxMessageBoxW. Stattdessen kümmert sich die Definition UNICODE um Letzteres. Zum Beweis stammt dies aus dem WinUser.h - Header von MS Visual Studio 2005:

#ifdef UNICODE
#define MessageBox  MessageBoxW
#else
#define MessageBox  MessageBoxA
#endif // !UNICODE

Dieser Fehler sollte mindestens auf utf8everywhere.org Korrigiert werden.

Ein Vorschlag:

Vielleicht sollte der Leitfaden ein Beispiel für die explizite Verwendung der Wide-String-Version einer Datenstruktur enthalten, damit sie weniger leicht übersehen/vergessen werden kann. Die Verwendung von Wide-String-Versionen von Datenstrukturen zusätzlich zur Verwendung von Wide-String-Versionen von Funktionen macht es noch weniger wahrscheinlich, dass versehentlich eine ANSI-String-Version einer solchen Funktion aufgerufen wird.

Beispiel des Beispiels:

WIN32_FIND_DATAW data; // Note the W at the end.
HANDLE hSearch = FindFirstFileW(widen("*.txt").c_str(), &data);
if (hSearch != INVALID_HANDLE_VALUE)
{
    FindClose(hSearch);
    MessageBoxW(nullptr, data.cFileName, nullptr, MB_OK);
}
6
Jelle Geerts

UTF-16 ist das bester Kompromiss zwischen Handling und Speicherplatz und wird daher von den meisten großen Plattformen (Win32, Java, .NET) zur internen Darstellung von Zeichenfolgen verwendet.

6

Ich habe den Punkt von UTF-16 nie verstanden. Wenn Sie die platzsparendste Darstellung wünschen, verwenden Sie UTF-8. Wenn Sie Text als feste Länge behandeln möchten, verwenden Sie UTF-32. Wenn Sie keine möchten, verwenden Sie UTF-16. Schlimmer noch, da alle in UTF-16 gebräuchlichen Zeichen (grundlegende mehrsprachige Ebene) in einen einzelnen Codepunkt passen, sind Fehler, die davon ausgehen, dass UTF-16 eine feste Länge hat, subtil und schwer zu finden, wohingegen, wenn Sie dies versuchen Mit UTF-8 schlägt Ihr Code schnell und laut fehl, sobald Sie versuchen, sich zu internationalisieren.

6
dsimcha

Jemand sagte, UCS4 und UTF-32 seien gleich. Nein, aber ich weiß, was du meinst. Einer von ihnen ist jedoch eine Kodierung des anderen. Ich wünschte, sie hätten von Anfang an daran gedacht, Endianness zu spezifizieren, damit wir nicht auch hier den Endianess-Kampf führen würden. Könnten sie das nicht kommen sehen? Zumindest UTF-8 ist überall gleich (es sei denn, jemand folgt der ursprünglichen Spezifikation mit 6 Bytes).

Wenn Sie UTF-16 verwenden, müssen Sie haben die Behandlung für Multibyte-Zeichen einschließen. Sie können nicht zum N-ten Zeichen wechseln, indem Sie 2N in ein Byte-Array indizieren. Sie müssen es gehen oder Zeichenindizes haben. Ansonsten hast du einen Bug geschrieben.

Der aktuelle Entwurf der C++ - Spezifikation besagt, dass UTF-32 und UTF-16 Little-Endian-, Big-Endian- und nicht spezifizierte Varianten haben können. "Ja wirklich?" Wenn Unicode angegeben hätte, dass jeder von Anfang an Little-Endian machen müsste, wäre alles einfacher gewesen. (Ich wäre auch mit Big-Endian in Ordnung gewesen.) Stattdessen haben einige Leute es auf die eine oder andere Weise implementiert, und jetzt stecken wir umsonst in der Albernheit fest. Manchmal ist es peinlich, Softwareentwickler zu sein.

5
Patrick Horgan

Ich denke nicht, dass es schädlich ist, wenn der Entwickler vorsichtig genug ist.
Und sie sollten diesen Kompromiss akzeptieren, wenn sie es auch gut wissen.

Als japanischer Softwareentwickler finde ich UCS-2 groß genug und die Begrenzung des Speicherplatzes vereinfacht anscheinend die Logik und reduziert den Laufzeitspeicher. Daher ist die Verwendung von utf-16 unter UCS-2-Beschränkung gut genug.

Es gibt ein Dateisystem oder eine andere Anwendung, bei der Codepunkte und Bytes als proportional angenommen werden, sodass garantiert werden kann, dass die rohe Codepunktnummer in einen Speicher mit fester Größe passt.

Ein Beispiel ist NTFS und VFAT geben UCS-2 an als Dateinamen-Speichercodierung.

Wenn dieses Beispiel wirklich erweitert werden soll, um UCS-4 zu unterstützen, könnte ich zustimmen, utf-8 trotzdem für alles zu verwenden, aber feste Länge hat gute Punkte wie:

  1. kann die Größe nach Länge garantieren (Datengröße und Codepunktlänge sind proportional)
  2. kann die Codierungsnummer für die Hash-Suche verwenden
  3. nicht komprimierte Daten haben eine angemessene Größe (im Vergleich zu utf-32/UCS-4).

In der Zukunft, wenn Speicher-/Verarbeitungsleistung selbst in eingebetteten Geräten billig ist, akzeptieren wir möglicherweise, dass das Gerät für zusätzliche Cache-Fehler oder Seitenfehler und zusätzliche Speichernutzung etwas langsam ist, aber dies wird in naher Zukunft wohl nicht passieren ...

2
holmes

"Sollte eine der beliebtesten Codierungen, UTF-16, als schädlich angesehen werden?"

Möglicherweise, aber die Alternativen sollten nicht unbedingt als viel besser angesehen werden.

Das grundlegende Problem ist, dass es viele verschiedene Konzepte gibt: Glyphen, Zeichen, Codepunkte und Byte-Sequenzen. Die Zuordnung zwischen diesen ist selbst mit Hilfe einer Normalisierungsbibliothek nicht trivial. (Zum Beispiel werden einige Zeichen in europäischen Sprachen, die mit einem lateinischen Skript geschrieben wurden, nicht mit einem einzigen Unicode-Codepunkt geschrieben. Und das ist das einfachere Ende der Komplexität!) Dies bedeutet, dass es ziemlich erstaunlich ist, alles richtig zu machen schwer; Es sind bizarre Fehler zu erwarten (und anstatt hier nur darüber zu stöhnen, sagen Sie es den Betreuern der betreffenden Software).

Die einzige Möglichkeit, UTF-16 als schädlich zu betrachten, im Gegensatz zu beispielsweise UTF-8, besteht darin, dass Codepunkte außerhalb von BMP (als Paar) auf andere Weise codiert werden von Ersatzzeichen). Wenn Code auf Codepunkte zugreifen oder diese durchlaufen möchte, bedeutet dies, dass er sich des Unterschieds bewusst sein muss. OTOH bedeutet, dass ein wesentlicher Teil des vorhandenen Codes, der "Zeichen" annimmt, immer in a passen kann Die Zwei-Byte-Menge - eine ziemlich häufige, wenn auch falsche Annahme - kann zumindest weiter funktionieren, ohne alles neu zu erstellen. Mit anderen Worten, zumindest erhalten Sie siehe die Zeichen, die nicht behandelt werden Recht!

Ich würde Ihre Frage auf den Kopf stellen und sagen, dass der ganze verdammte Shebang von Unicode als schädlich angesehen werden sollte und jeder eine 8-Bit-Codierung verwenden sollte, außer ich habe (in den letzten 20 Jahren) gesehen, wohin das führt: schrecklich Verwirrung über die verschiedenen ISO 8859-Codierungen sowie die gesamte für Cyrillic und die EBCDIC-Suite verwendete Codierung, und… nun, Unicode für all seine Fehler übertrifft dies. Wenn es nur kein so böser Kompromiss zwischen den Missverständnissen verschiedener Länder wäre.

1
Donal Fellows