Was ist der beste Weg, um eine Zeichenkette von Unicode nach ASCII zu konvertieren, ohne die Länge zu ändern (das ist in meinem Fall sehr wichtig)? Auch die Zeichen ohne Konvertierungsprobleme müssen sich an den gleichen Stellen befinden wie in der ursprünglichen Zeichenkette. Also muss ein "Ä" in "A" umgewandelt werden und nicht etwas kryptisches, das mehr Zeichen hat.
Bearbeiten:
@novalis - Solche Symbole (zum Beispiel von asiatischen Sprachen) sollten nur in einige Platzhalter konvertiert werden. Ich bin nicht so interessiert an diesen Worten oder was sie bedeuten.
@MtnViewMark - Ich muss unter allen Umständen die Anzahl aller Zeichen und die Position der ASCII-Zeichen beibehalten.
Hier noch ein paar Infos: Ich habe einige Text-Mining-Tools, die nur ASCII-Strings verarbeiten können. Der meiste Text, der verarbeitet werden sollte, ist in Englisch, aber einige enthalten nicht-ASCII-Zeichen. Ich bin nicht an diesen Wörtern interessiert, aber ich muss sicher sein, dass die Wörter, an denen ich interessiert bin (diejenigen, die nur ASCII-Zeichen enthalten), sich nach der String-Konvertierung an den gleichen Positionen befinden.
Wie in dieser Antwort angegeben, ist die folgender Code sollte funktionieren:
%Vor%Ausgabe ist
%Vor%Sie entfernen also zuerst diactrical Markierungen, die in ascii konvertieren. Nicht-ASCII-Zeichen werden zu Fragezeichen.
Verwenden Sie java.text.Normalizer.normalize()
mit Normalizer.Form.NFD
und filtern Sie dann die Nicht-ASCII-Zeichen aus.
Vorbehalt: Ich kenne Java nicht. Nur ein bisschen über Zeichensätze.
Sie geben nicht an, welchen Zeichensatz Sie genau verwenden.
Aber egal, was Sie verwenden, es ist unmöglich, eine Unicode-Zeichenkette in ASCII zu konvertieren. und behalten die ursprüngliche Länge und Zeichenpositionen bei, einfach weil ein Unicode-Zeichensatz verwendet wird mehrere Bytes für einige Zeichen (offensichtlich).
Die einzige Ausnahme, die ich kenne, wäre eine UTF-8-Zeichenfolge, die nur ASCII-Zeichen enthält: Diese Zeichenfolge ist in UTF-8 und ASCII bereits identisch, da UTF-8 Multibyte-Zeichen nur bei Bedarf verwendet. (Ich weiß nichts über die anderen Unicode-Varianten, möglicherweise gibt es andere dynamische).
Die einzige Problemumgehung, die ich sehen kann, ist das Hinzufügen eines Leerzeichens zu einem Sonderzeichen, das durch ein ASCII-Zeichen ersetzt wurde, aber das würde die Zeichenkette beschädigen ( Göteborg
in UTF8 müsste Go teborg
werden, um die Länge beizubehalten) .
Vielleicht möchten Sie näher erläutern, was Sie erreichen wollen / müssen, damit die Leute hier Abhilfe schaffen können.
Wie Paul Taylor erwähnte: Es gibt ein Problem bei der Verwendung von Normalizer, wenn Sie das Projekt in pre-1.6 und auch in 1.6 und höherem Java kompilierbar / lauffähig machen wollen. Sie werden in Schwierigkeiten geraten, da Normalizer in verschiedenen Paketen ( java.text.Normalizer
(für 1.6) statt sun.text.Normalizer
(für vor-1.6)) ist und eine andere Methodensignatur aufweist.
Normalerweise wird empfohlen, reflection zu verwenden, um die entsprechende Normalizer.normalize () -Methode aufzurufen. ( Beispiel könnte hier gefunden werden ).
Wenn Sie jedoch keine Spiegelung in Ihren Code einfügen möchten, können Sie icu4j Bibliothek . Es enthält com.ibm.icu.text.Normalizer
class mit normalize()
Methode, die den gleichen Job ausführen wie java.text.Normalizer / sun.text.Normalizer. Icu-Bibliothek hat (sollte) eine eigene Implementierung von Normalizer haben, damit Sie Ihr Projekt mit der Bibliothek teilen können und das sollte Java-unabhängig sein.
Nachteil ist, dass die icu-Bibliothek ziemlich groß ist.
Wenn Sie die Normalizer-Klasse nur zum Entfernen von Akzenten / Diakritika aus Strings verwenden, gibt es auch einen anderen Weg. Sie können Apache commons lang-Bibliothek (Version 3) verwenden, die StringUtils
mit der Methode stripAccents()
enthält:
Lang3-Bibliothek verwendet wahrscheinlich Reflektion, um den entsprechenden Normalizer gemäß der Java-Version aufzurufen. Der Vorteil ist, dass Sie in Ihrem Code keine Reflexionsprobleme haben.
Eine Sache mit Normalizer ist die vor Java 1.6 im Paket sun.text, während sie in 1.6 im Paket java.text und der it-Signatur geändert wurde. Wenn Ihre Anwendung also auf beiden Plattformen ausgeführt werden muss, müssen Sie Reflektion verwenden.
Eine alternative benutzerdefinierte Lösung wird als techniwue 3 hier
beschrieben