Ich falle in ein überraschendes Problem.
Ich habe eine Textdatei in meine Anwendung geladen und habe eine Logik, die den Wert mit µ vergleicht.
Und mir wurde klar, dass selbst wenn die Texte gleich sind, der Vergleichswert falsch ist.
Console.WriteLine("μ".Equals("µ")); // returns false
Console.WriteLine("µ".Equals("µ")); // return true
In der späteren Zeile wird das Zeichen µ kopiert und eingefügt.
Dies sind jedoch möglicherweise nicht die einzigen Zeichen, die so sind.
Gibt es in C # eine Möglichkeit, die Zeichen zu vergleichen, die gleich aussehen, aber tatsächlich unterschiedlich sind?
Antworten:
In vielen Fällen können Sie normalisieren beide der Unicode - Zeichen auf eine gewisse Normalisierung Form vor ihnen zu vergleichen, und sie sollten übereinstimmen können. Welche Normalisierungsform Sie verwenden müssen, hängt natürlich von den Zeichen selbst ab. Nur weil sie gleich aussehen , heißt das nicht unbedingt, dass sie denselben Charakter repräsentieren. Sie müssen auch überlegen, ob es für Ihren Anwendungsfall geeignet ist - siehe den Kommentar von Jukka K. Korpela.
Wenn Sie sich in dieser speziellen Situation auf die Links in Tonys Antwort beziehen , sehen Sie, dass in der Tabelle für U + 00B5 Folgendes angegeben ist :
Dies bedeutet, dass U + 00B5, das zweite Zeichen in Ihrem ursprünglichen Vergleich, in U + 03BC, das erste Zeichen, zerlegt werden kann.
Sie normalisieren also die Zeichen mit vollständiger Kompatibilitätszerlegung mit den Normalisierungsformularen KC oder KD. Hier ist ein kurzes Beispiel, das ich geschrieben habe, um zu demonstrieren:
Einzelheiten zu Unicode - Normalisierung und die unterschiedlichen Normalisierungsformen beziehen sie auf
System.Text.NormalizationForm
und die Unicode - Spezifikation .quelle
Da es sich wirklich um verschiedene Symbole handelt, auch wenn sie gleich aussehen, ist der erste der eigentliche Buchstabe und hat
code = 956 (0x3BC)
Zeichen und der zweite ist das Mikrozeichen und hat181 (0xB5)
.Verweise:
Wenn Sie sie also vergleichen möchten und sie gleich sein müssen, müssen Sie sie manuell behandeln oder vor dem Vergleich ein Zeichen durch ein anderes ersetzen. Oder verwenden Sie den folgenden Code:
Und die Demo
quelle
Beide haben unterschiedliche Zeichencodes: Weitere Informationen finden Sie hier
Wo, 1. ist:
quelle
Für das spezifische Beispiel von
μ
(mu) undµ
(Mikrozeichen) hat das letztere eine Kompatibilitätszerlegung mit dem ersteren, so dass Sie den String auf oder normalisieren könnenFormKC
FormKD
die Mikrozeichen in mus umwandeln können.Es gibt jedoch viele Zeichensätze, die ähnlich aussehen, aber unter keinem Unicode-Normalisierungsformular gleichwertig sind. Zum Beispiel
A
(lateinisch),Α
(griechisch) undА
(kyrillisch). Die Unicode-Website enthält eine Datei confusables.txt mit einer Liste dieser Dateien, die Entwicklern helfen soll, sich vor Homograph-Angriffen zu schützen . Bei Bedarf können Sie diese Datei analysieren und eine Tabelle zur „visuellen Normalisierung“ von Zeichenfolgen erstellen.quelle
ToUpper
/ToLower
schwierig umzusetzen. Sie müssen haben"B".ToLower()
seineb
in Englisch , aberβ
in der griechischen undв
in russischer Sprache . Derzeiti
benötigen nur Türkisch (ohne Punkt ) und einige andere Sprachen andere als die Standardregeln für die Schreibweise.Suchen Sie beide Zeichen in einer Unicode-Datenbank und sehen Sie den Unterschied .
Einer ist der griechische Kleinbuchstabe
µ
und der andere ist das Mikrozeichenµ
.quelle
BEARBEITEN Nach dem Zusammenführen dieser Frage mit Wie man 'μ' und 'µ' in C # vergleicht
Originalantwort gepostet:
BEARBEITEN Nach dem Lesen der Kommentare ist es nicht gut, die obige Methode zu verwenden, da sie möglicherweise falsche Ergebnisse für eine andere Art von Eingaben liefert. Dazu sollten wir Normalisieren mit vollständiger Kompatibilitätszerlegung verwenden, wie im Wiki erwähnt . (Dank der Antwort von BoltClock )
Ausgabe
Beim Lesen von Informationen in Unicode_equivalence habe ich gefunden
Um die Äquivalenz zu vergleichen, sollten wir normalerweise die
FormKC
NFKC-Normalisierung oder dieFormKD
NFKD-Normalisierung verwenden.Ich war wenig neugierig, mehr über alle Unicode-Zeichen zu erfahren, also habe ich ein Beispiel erstellt, das über alle Unicode-Zeichen in iteriert,
UTF-16
und ich habe einige Ergebnisse erhalten, die ich diskutieren möchteFormC
undFormD
normalisierte Werte nicht äquivalent warenTotal: 12,118
Character (int value): 192-197, 199-207, 209-214, 217-221, 224-253, ..... 44032-55203
FormKC
undFormKD
normalisierte Werte nicht äquivalent warenTotal: 12,245
Character (int value): 192-197, 199-207, 209-214, 217-221, 224-228, ..... 44032-55203, 64420-64421, 64432-64433, 64490-64507, 64512-64516, 64612-64617, 64663-64667, 64735-64736, 65153-65164, 65269-65274
FormC
undFormD
normalisierter Wert nicht äquivalent waren,FormKC
undFormKD
normalisierte Werte waren ebenfalls nicht äquivalent, mit Ausnahme dieser Zeichen.Zeichen:
901 '΅', 8129 '῁', 8141 '῍', 8142 '῎', 8143 '῏', 8157 '῝', 8158 '῞'
, 8159 '῟', 8173 '῭', 8174 '΅'
FormKC
undFormKD
normalisierter Wert nicht äquivalent waren, aber dortFormC
undFormD
normalisierte Werte waren äquivalenteTotal: 119
Zeichen:
452 'DŽ' 453 'Dž' 454 'dž' 12814 '㈎' 12815 '㈏' 12816 '㈐' 12817 '㈑' 12818 '㈒' 12819 '㈓' 12820 '㈔' 12821 '㈕', 12822 '㈖' 12823 '㈗' 12824 '㈘' 12825 '㈙' 12826 '㈚' 12827 '㈛' 12828 '㈜' 12829 '㈝' 12830 '㈞' 12910 '㉮' 12911 '㉯' 12912 '㉰' 12913 '㉱' 12914 '㉲' 12915 '㉳' 12916 '㉴' 12917 '㉵' 12918 '㉶' 12919 '㉷' 12920 '㉸' 12921 '㉹' 12922 '㉺' 12923 '㉻' 12924 '㉼' 12925 '㉽' 12926 '㉾' 13056 '㌀' 13058 '㌂' 13060 '㌄' 13063 '㌇' 13070 '㌎' 13071 '㌏' 13072 '㌐' 13073 '㌑' 13075 '㌓' 13077 '㌕' 13080 '㌘' 13081 '㌙' 13082 '㌚' 13086 '㌞' 13089 '㌡' 13092 '㌤' 13093 '㌥' 13094 '㌦' 13099 '㌫' 13100 '㌬' 13101 '㌭' 13102 '㌮' 13103 '㌯' 13104 '㌰' 13105 '㌱' 13106 '㌲' 13108 '㌴' 13111 '㌷' 13112 '㌸' 13114 '㌺' 13115 '㌻' 13116 '㌼' 13117 '㌽' 13118 '㌾' 13120 '㍀' 13130 '㍊' 13131 '㍋' 13132 '㍌' 13134 '㍎' 13139 '㍓' 13140 '㍔' 13142 '㍖' .......... ﺋ' 65164 'ﺌ' 65269 'ﻵ' 65270 'ﻶ' 65271 'ﻷ' 65272 'ﻸ' 65273 'ﻹ' 65274'
ArgumentException
wenn sie es versuchenTotal:2081
Characters(int value): 55296-57343, 64976-65007, 65534
Diese Links können sehr hilfreich sein, um zu verstehen, welche Regeln für die Unicode-Äquivalenz gelten
quelle
"m".ToUpper().Equals("µ".ToUpper());
und"M".ToUpper().Equals("µ".ToUpper());
ist auch wahr. Dies ist möglicherweise nicht wünschenswert.Höchstwahrscheinlich gibt es zwei verschiedene Zeichencodes, die (sichtbar) dasselbe Zeichen bilden. Obwohl sie technisch nicht gleich sind, sehen sie gleich aus. Schauen Sie sich die Zeichentabelle an und prüfen Sie, ob es mehrere Instanzen dieses Zeichens gibt. Oder drucken Sie den Zeichencode der beiden Zeichen in Ihrem Code aus.
quelle
Sie fragen "wie man sie vergleicht", sagen uns aber nicht, was Sie tun möchten.
Es gibt mindestens zwei Möglichkeiten, sie zu vergleichen:
Entweder Sie vergleichen sie direkt so wie Sie sind und sie sind unterschiedlich
Oder Sie verwenden die Unicode-Kompatibilitätsnormalisierung, wenn Sie einen Vergleich benötigen, der übereinstimmt.
Es könnte jedoch ein Problem geben, da durch die Normalisierung der Unicode-Kompatibilität viele andere Zeichen gleich verglichen werden. Wenn Sie möchten, dass nur diese beiden Zeichen gleich behandelt werden, sollten Sie Ihre eigenen Normalisierungs- oder Vergleichsfunktionen ausführen.
Für eine spezifischere Lösung müssen wir Ihr spezifisches Problem kennen. In welchem Kontext sind Sie auf dieses Problem gestoßen?
quelle
Wenn ich pedantisch sein möchte, würde ich sagen, dass Ihre Frage keinen Sinn ergibt, aber da wir uns Weihnachten nähern und die Vögel singen, werde ich damit fortfahren.
Zunächst einmal, die 2 Einheiten , die Sie vergleichen versuchen , sind
glyph
s, eine Glyphe Teil einer Reihe von Glyphen durch das, was vorgesehen ist , in der Regel wissen , als „font“, die Sache , die in der Regel in eine kommtttf
,otf
oder was auch immer Dateiformat Sie sind mit.Die Glyphen sind eine Darstellung eines bestimmten Symbols, und da es sich um eine Darstellung handelt, die von einer bestimmten Menge abhängt, können Sie nicht einfach zwei ähnliche oder sogar "bessere" identische Symbole erwarten. Diese Phrase ist nicht sinnvoll Wenn Sie den Kontext berücksichtigen, sollten Sie zumindest angeben, welche Schriftart oder welchen Satz von Glyphen Sie bei der Formulierung einer solchen Frage berücksichtigen.
Was normalerweise verwendet wird, um ein Problem zu lösen, das demjenigen ähnelt, auf das Sie stoßen, ist eine OCR, im Wesentlichen eine Software, die Glyphen erkennt und vergleicht, wenn C # eine OCR bereitstellt standardmäßig weiß ich das nicht, aber es ist im Allgemeinen eine wirklich schlechte Idee, wenn Sie keine OCR wirklich brauchen und wissen, was Sie damit machen sollen.
Möglicherweise interpretieren Sie ein Physikbuch als ein altes griechisches Buch, ohne die Tatsache zu erwähnen, dass OCR im Allgemeinen ressourcenintensiv sind.
Es gibt einen Grund, warum diese Zeichen so lokalisiert sind, wie sie lokalisiert sind. Tun Sie das einfach nicht.
quelle
Mit der
DrawString
Methode können beide Zeichen mit demselben Schriftstil und derselben Schriftgröße gezeichnet werden. Nachdem zwei Bitmaps mit Symbolen generiert wurden, können diese Pixel für Pixel verglichen werden.Vorteil dieser Methode ist, dass Sie nicht nur absolut gleiche Zeichen vergleichen können, sondern auch ähnliche (mit definitiver Toleranz).
quelle