Verwenden Sie java.text.Normalizer
, um dies für Sie zu erledigen.
string = Normalizer.normalize(string, Normalizer.Form.NFD);
// or Normalizer.Form.NFKD for a more "compatable" deconstruction
Dadurch werden alle Akzentzeichen von den Zeichen getrennt. Dann müssen Sie nur noch jedes Zeichen mit einem Buchstaben vergleichen und diejenigen wegwerfen, die es nicht sind.
string = string.replaceAll("[^\\p{ASCII}]", "");
Wenn Ihr Text in Unicode vorliegt, sollten Sie stattdessen Folgendes verwenden:
string = string.replaceAll("\\p{M}", "");
Stimmt bei Unicode \\P{M}
mit dem Basiszeichen überein und \\p{M}
(Kleinbuchstaben) mit jedem Akzent.
Vielen Dank an GarretWilson für den Zeiger und reguläre-expressions.info für die großartige Unicode-Anleitung.
string.replaceAll("\\p{M}", "")
. Weitere Informationen finden Sie unter reguläre-Ausdrücke.info/unicode.html .Ab 2011 können Sie Apache Commons StringUtils.stripAccents (Eingabe) verwenden (seit 3.0):
Hinweis:
Die akzeptierte Antwort (Erick Robertson's) funktioniert nicht für Ø oder Ł. Apache Commons 3.5 funktioniert auch nicht für Ø, aber für Ł. Nachdem ich den Wikipedia-Artikel für Ø gelesen habe , bin ich mir nicht sicher, ob er durch "O" ersetzt werden sollte: Es ist ein separater Buchstabe auf Norwegisch und Dänisch, alphabetisch nach "z". Dies ist ein gutes Beispiel für die Einschränkungen des Ansatzes "Streifenakzente".
quelle
Die Lösung von @ virgo47 ist sehr schnell, aber ungefähr. Die akzeptierte Antwort verwendet Normalizer und einen regulären Ausdruck. Ich habe mich gefragt, welchen Teil der Zeit Normalizer im Vergleich zum regulären Ausdruck benötigt, da das Entfernen aller Nicht-ASCII-Zeichen ohne regulären Ausdruck erfolgen kann:
Kleine zusätzliche Beschleunigungen können erzielt werden, indem Sie in ein char [] schreiben und nicht toCharArray () aufrufen, obwohl ich nicht sicher bin, ob die Verringerung der Codeklarheit dies verdient:
Diese Variation hat den Vorteil der Richtigkeit derjenigen, die Normalizer verwendet, und eines Teils der Geschwindigkeit derjenigen, die eine Tabelle verwendet. Auf meinem Computer ist diese Antwort ungefähr 4x schneller als die akzeptierte Antwort und 6,6x bis 7x langsamer als die von @ virgo47 (die akzeptierte Antwort ist ungefähr 26x langsamer als die von @ virgo47 auf meinem Computer).
quelle
out
Die Größe muss an die Anzahl der gültigen Zeichen angepasst werden,j
bevor das Zeichenfolgenobjekt erstellt wird.flattenToAscii
erzeugt das Ergebnis "aa ..", wobei Punkte \ u0000 darstellen. Das ist nicht gut. Die erste Frage ist - wie man "nicht normalisierbare" Zeichen darstellt. Nehmen wir an, es wird sein? Oder wir können NULL char dort lassen, aber auf jeden Fall müssen wir die korrekte Position dieser beibehalten (genau wie es die Regex-Lösung tut). Dafür muss das if in der Schleife ungefähr so sein:if (c <= '\u007F') out[j++] = c; else if (Character.isLetter(c)) out[j++] = '?';
Es wird es etwas verlangsamen, aber es muss an erster Stelle korrekt sein. ;-)isLetter
) nicht die richtige, aber ich habe keine bessere gefunden. Ich bin kein Unicode-Experte, daher weiß ich nicht, wie ich die Klasse des einzelnen Zeichens, das das ursprüngliche Zeichen ersetzt, besser identifizieren kann. Buchstaben funktionieren für die meisten Anwendungen / Verwendungen einwandfrei.BEARBEITEN: Wenn Sie nicht mit Java <6 feststecken und die Geschwindigkeit nicht kritisch ist und / oder die Übersetzungstabelle zu einschränkend ist, verwenden Sie die Antwort von David. Der Punkt ist,
Normalizer
(in Java 6 eingeführt) anstelle der Übersetzungstabelle innerhalb der Schleife zu verwenden.Dies ist zwar keine "perfekte" Lösung, funktioniert aber gut, wenn Sie den Bereich kennen (in unserem Fall Latin1,2), vor Java 6 gearbeitet haben (allerdings kein wirkliches Problem) und viel schneller als die am meisten vorgeschlagene Version (möglicherweise oder möglicherweise) kein Problem sein):
Tests auf meiner HW mit 32-Bit-JDK zeigen, dass dies eine Konvertierung von àèéľšťč89FDČ zu aeelstc89FDC 1 Million Mal in ~ 100 ms durchführt, während Normalizer es in 3,7 s (37x langsamer) schafft. Wenn Ihre Anforderungen in Bezug auf die Leistung liegen und Sie den Eingabebereich kennen, ist dies möglicherweise das Richtige für Sie.
Genießen :-)
quelle
arbeitete für mich. Die Ausgabe des obigen Snippets gibt "aee", was ich wollte, aber
hat keine Substitution gemacht.
quelle
Je nach Sprache werden diese möglicherweise nicht als Akzente (die den Klang des Buchstabens verändern), sondern als diakritische Zeichen betrachtet
https://en.wikipedia.org/wiki/Diacritic#Languages_with_letters_containing_diacritics
"Bosnisch und Kroatisch haben die Symbole č, ć, đ, š und ž, die als separate Buchstaben betrachtet werden und als solche in Wörterbüchern und anderen Kontexten aufgeführt sind, in denen Wörter in alphabetischer Reihenfolge aufgeführt sind."
Wenn Sie sie entfernen, ändert sich möglicherweise die Bedeutung des Wortes oder die Buchstaben werden in völlig andere Buchstaben geändert.
quelle
Ich habe das gleiche Problem im Zusammenhang mit der Überprüfung der Strings-Gleichheit festgestellt. Einer der Vergleichsstrings hat den ASCII-Zeichencode 128-255 .
Verwenden Sie den folgenden Code für verschiedene Räume und ihre Byte-Codes:
wiki for List_of_Unicode_characters
➩ ASCII-Transliterationen von Unicode-Zeichenfolgen für Java.
unidecode
➩ Verwenden von
Guava
: Google CoreLibraries for Java
.Verwenden Sie für die URL-Codierung für den Speicherplatz die Guava-Bibliothek.
➩ Um dieses Problem
String.replaceAll()
bei einigen zu überwindenRegularExpression
.➩ Verwenden von java.text.Normalizer.Form . Diese Aufzählung enthält Konstanten der vier Unicode-Normalisierungsformulare, die im Unicode-Standardanhang Nr. 15 - Unicode-Normalisierungsformulare beschrieben sind, sowie zwei Methoden für den Zugriff darauf.
Testen von Zeichenfolgen und Ausgaben auf verschiedenen Ansätzen wie ➩ Unidecode, Normalizer, StringUtils .
Die Verwendung von Unidecode ist der
best choice
unten gezeigte endgültige Code.quelle
Ich schlage Junidecode vor . Es kann nicht nur 'Ł' und 'Ø' verarbeiten, sondern eignet sich auch gut zum Transkribieren von anderen Alphabeten wie Chinesisch in das lateinische Alphabet.
quelle
Die @ David Conrad-Lösung ist die schnellste, die ich mit dem Normalizer versucht habe, aber es gibt einen Fehler. Grundsätzlich werden Zeichen entfernt, die keine Akzente darstellen, z. B. chinesische Zeichen und andere Buchstaben wie æ. Die Zeichen, die wir entfernen möchten, sind Zeichen ohne Abstand, Zeichen, die in der endgültigen Zeichenfolge keine zusätzliche Breite einnehmen. Diese Zeichen mit der Breite Null werden im Grunde genommen in einem anderen Zeichen kombiniert. Wenn Sie sie als Zeichen isoliert sehen können, zum Beispiel wie folgt, ist meine Vermutung, dass sie mit dem Leerzeichen kombiniert sind.
quelle
Eine der besten Möglichkeiten , Regex und Normalizer zu verwenden, wenn Sie keine Bibliothek haben, ist:
Dies ist effizienter als replaceAll ("[^ \ p {ASCII}]", "")) und wenn Sie keine diakritischen Zeichen benötigen (genau wie in Ihrem Beispiel).
Andernfalls müssen Sie das Muster p {ASCII} verwenden.
Grüße.
quelle
Ich denke, die beste Lösung besteht darin, jedes Zeichen in HEX umzuwandeln und durch ein anderes HEX zu ersetzen. Es ist, weil es 2 Unicode-Typisierung gibt:
Zum Beispiel unterscheidet sich "Ồ", das von Composite Unicode geschrieben wurde, von "Ồ", das von Precomposed Unicode geschrieben wurde. Sie können meine Beispielzeichen kopieren und konvertieren, um den Unterschied zu sehen.
Ich habe diese Funktion für einige Banken entwickelt, um die Informationen vor dem Senden an die Kernbank zu konvertieren (normalerweise wird Unicode nicht unterstützt), und dieses Problem trat auf, wenn die Endbenutzer mehrere Unicode-Eingaben zur Eingabe der Daten verwenden. Ich denke, die Umstellung auf HEX und das Ersetzen ist der zuverlässigste Weg.
quelle
Falls jemand Schwierigkeiten hat, dies in Kotlin zu tun, funktioniert dieser Code wie ein Zauber. Um Inkonsistenzen zu vermeiden, verwende ich auch .toUpperCase und Trim (). dann habe ich diese Funktion gewirkt:
}}
Um diesen Spaß zu nutzen, gießen Sie den Code wie folgt:
quelle