Gibt es eine Möglichkeit, Akzente zu entfernen und eine ganze Zeichenfolge in reguläre Buchstaben umzuwandeln?

262

Gibt es eine bessere Möglichkeit, Akzente zu entfernen und diese Buchstaben regelmäßig zu machen, als String.replaceAll()Methoden anzuwenden und Buchstaben einzeln zu ersetzen? Beispiel:

Eingang: orčpžsíáýd

Ausgabe: orcpzsiayd

Es müssen nicht alle Buchstaben mit Akzenten wie dem russischen oder dem chinesischen Alphabet enthalten sein.

Martin
quelle

Antworten:

386

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.

Erick Robertson
quelle
7
Dadurch wird der reguläre Ausdruck jedes Mal kompiliert. Dies ist in Ordnung, wenn Sie ihn nur einmal benötigen. Wenn Sie dies jedoch mit viel Text tun müssen, ist das Vorkompilieren des regulären Ausdrucks ein Gewinn.
David Conrad
3
Beachten Sie, dass nicht alle lateinischen Buchstaben in ASCII + Akzente zerfallen. Dies wird zB töten. "Lateinischer Großbuchstabe l mit Strich" in polnischer Sprache.
Michał Politowski
12
Dies ist ein guter Ansatz, aber das Entfernen aller Nicht-ASCII-Zeichen ist übertrieben und wird wahrscheinlich Dinge entfernen, die Sie nicht möchten, wie andere angegeben haben. Es wäre besser, alle Unicode- "Markierungen" zu entfernen. einschließlich Nicht-Abstandsmarkierungen, Abstands- / Kombinationsmarkierungen und umschließender Markierungen. Sie können dies mit tun string.replaceAll("\\p{M}", ""). Weitere Informationen finden Sie unter reguläre-Ausdrücke.info/unicode.html .
Garret Wilson
4
Sie möchten wahrscheinlich Normalizer.Form.NFKD anstelle von NFD verwenden - NFKD konvertiert Dinge wie Ligaturen in ASCII-Zeichen (z. B. fi zu fi), NFD tut dies nicht.
Brust 8
2
@ brusterm8, interessanterweise konvertiert NFKD "fi" in "fi", aber es konvertiert nicht "Æ" in "AE". Ich denke, ich muss die Unicode-Daten aufrufen, um herauszufinden, warum, aber es war nicht das, was ich erwartet hatte.
Garret Wilson
136

Ab 2011 können Sie Apache Commons StringUtils.stripAccents (Eingabe) verwenden (seit 3.0):

    String input = StringUtils.stripAccents("Tĥïŝ ĩš â fůňķŷ Šťŕĭńġ");
    System.out.println(input);
    // Prints "This is a funky String"

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".

DavidS
quelle
2
Ich sehe, es gibt einen offenen Fehlerbericht für Ł , @KarolS. Jemand hat eine Pull-Anfrage eingereicht, die jedoch einige Tests nicht bestanden hat und seit Juli letzten Jahres nicht mehr aktualisiert wurde.
DavidS
1
Vor 5 Tagen gab es ein Update und die Pull-Anfrage wurde zusammengeführt.
EpicPandaForce
6
Commons Lang 3.5 wurde vor einigen Tagen veröffentlicht. Ich habe bestätigt, dass es jetzt funktioniert. Bei Ø funktioniert das nicht. Wenn ich den Wiki-Artikel für Ø lese , bin ich mir nicht sicher, ob er durch "O" ersetzt werden soll: 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".
DavidS
2
Wenn Sie die Bibliothek nicht einschließen möchten, können Sie die beiden an dieser Funktion beteiligten Methoden problemlos aus dem Quellcode unter commons.apache.org/proper/commons-lang/apidocs/src-html/org/…
lujop
2
Als Däne ist das dänische / norwegische ø ebenso wie das französische œ und das deutsche / schwedische / ungarische / estnische usw. ö eine kurze Art, oe zu schreiben. Abhängig von Ihrem Zweck kann dies die gewünschte Substitution sein.
Ole VV
57

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:

import java.text.Normalizer;

public class Strip {
    public static String flattenToAscii(String string) {
        StringBuilder sb = new StringBuilder(string.length());
        string = Normalizer.normalize(string, Normalizer.Form.NFD);
        for (char c : string.toCharArray()) {
            if (c <= '\u007F') sb.append(c);
        }
        return sb.toString();
    }
}

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:

public static String flattenToAscii(String string) {
    char[] out = new char[string.length()];
    string = Normalizer.normalize(string, Normalizer.Form.NFD);
    int j = 0;
    for (int i = 0, n = string.length(); i < n; ++i) {
        char c = string.charAt(i);
        if (c <= '\u007F') out[j++] = c;
    }
    return new String(out);
}

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).

David Conrad
quelle
2
outDie Größe muss an die Anzahl der gültigen Zeichen angepasst werden, jbevor das Zeichenfolgenobjekt erstellt wird.
Lefteris E
4
Ich habe Einwände gegen diese Lösung. Stellen Sie sich die Eingabe "æøåá" vor. Der Strom flattenToAsciierzeugt 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. ;-)
Jungfrau47
Ad mein letzter Kommentar (schade, dass sie nicht länger sein können) - vielleicht ist positive Einstellung ( 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.
Jungfrau47
1
Sie möchten wahrscheinlich Normalizer.Form.NFKD anstelle von NFD verwenden - NFKD konvertiert Dinge wie Ligaturen in ASCII-Zeichen (z. B. fi zu fi), NFD tut dies nicht.
Brust 8
2
Für uns wollten wir den Charakter komplett entfernen. Um sicherzustellen, dass keine nachgestellten Nullzeichen vorhanden sind, habe ich sie mit einem alternativen String-Konstruktor entfernt: return new String (out, 0, j);
Mike Samaras
30

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):

    /**
 * Mirror of the unicode table from 00c0 to 017f without diacritics.
 */
private static final String tab00c0 = "AAAAAAACEEEEIIII" +
    "DNOOOOO\u00d7\u00d8UUUUYI\u00df" +
    "aaaaaaaceeeeiiii" +
    "\u00f0nooooo\u00f7\u00f8uuuuy\u00fey" +
    "AaAaAaCcCcCcCcDd" +
    "DdEeEeEeEeEeGgGg" +
    "GgGgHhHhIiIiIiIi" +
    "IiJjJjKkkLlLlLlL" +
    "lLlNnNnNnnNnOoOo" +
    "OoOoRrRrRrSsSsSs" +
    "SsTtTtTtUuUuUuUu" +
    "UuUuWwYyYZzZzZzF";

/**
 * Returns string without diacritics - 7 bit approximation.
 *
 * @param source string to convert
 * @return corresponding string without diacritics
 */
public static String removeDiacritic(String source) {
    char[] vysl = new char[source.length()];
    char one;
    for (int i = 0; i < source.length(); i++) {
        one = source.charAt(i);
        if (one >= '\u00c0' && one <= '\u017f') {
            one = tab00c0.charAt((int) one - '\u00c0');
        }
        vysl[i] = one;
    }
    return new String(vysl);
}

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 :-)

Jungfrau47
quelle
1
Ein Großteil der Langsamkeit der vorgeschlagenen Version ist auf den regulären Ausdruck zurückzuführen, nicht auf den Normalisierer. Die Verwendung von Normalizer, aber das Entfernen der Nicht-ASCII-Zeichen "von Hand" ist schneller, obwohl immer noch nicht so schnell wie Ihre Version. Aber es funktioniert für alle Unicode anstatt nur für latin1 und latin2.
David Conrad
Ich habe dies erweitert, um mit mehr Zeichen zu arbeiten. Pastebin.com/FAAm6a2j . Beachten Sie, dass es mit mehrfarbigen Zeichen wie DŽ (DZ) nicht richtig funktioniert. Es wird nur 1 Zeichen daraus erzeugt. Außerdem verwendet meine Funktion char anstelle von Strings, was schneller ist, wenn Sie sowieso char verarbeiten, sodass Sie nicht konvertieren müssen.
James T
Hey, ich verstehe nicht, wofür diese Buchstaben auf dem Feld tab00c0 stehen. Zum Beispiel "AAAAAAACEEEEIIII" oder "lLlNnNnNnnNnOoOo" usw. Noch nie gesehen. Wo hast du sie gefunden? Warum verwenden Sie nicht einfach die entsprechenden Codes?
ThanosFisherman
@ThanosF versuchen Sie einfach, den Code durchzugehen (bei Bedarf mit Debugger). Dies gilt für jedes Zeichen in einer Zeichenfolge: "Liegt dieses Zeichen zwischen \ u00c0 und \ u017f? Wenn ja, ersetzen Sie es durch ein 7-Bit-ASCII-Zeichen aus der Tabelle." Die Tabelle enthält nur zwei Codierungsseiten (Latein 1 und 2) mit ihren 7-Bit-Entsprechungen. Wenn es sich also um ein Zeichen mit dem Code \ u00e0 (à) handelt, wird die 7-Bit-Näherung von der 32. Position der Tabelle (e0-c0 = 32) übernommen - das ist "a". Einige Zeichen sind keine Buchstaben, diese bleiben dort mit ihrem Code.
Jungfrau47
Danke für Ihre Erklärung. Wo finde ich diese Codierungsseiten, damit ich diese Variable auf meine Sprache erweitern kann? (Griechisch) Akzeptierte Antwort ersetzt bereits Buchstaben mit griechischem Akzent, aber ich wollte auch Ihre Methode ausprobieren und einige Benchmarks
ausführen
22
System.out.println(Normalizer.normalize("àèé", Normalizer.Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+", ""));

arbeitete für mich. Die Ausgabe des obigen Snippets gibt "aee", was ich wollte, aber

System.out.println(Normalizer.normalize("àèé", Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", ""));

hat keine Substitution gemacht.

Nico
quelle
1
Dies bestätigen ... normalerweise funktioniert ASCII einwandfrei, aber ich habe dieses Problem unter Linux (64b) mit JRockit (1.6.0_29 64b) festgestellt. Ich kann es mit keinem anderen Setup bestätigen, kann diese Korellation nicht bestätigen, aber ich kann bestätigen, dass die andere vorgeschlagene Lösung funktioniert hat, und dafür stimme ich ab. :-) (Übrigens: Es hat einige Ersetzungen vorgenommen, aber nicht genug, es hat sich zum Beispiel in U geändert, aber nicht in a.)
virgo47
1
Sie möchten wahrscheinlich Normalizer.Form.NFKD anstelle von NFD verwenden - NFKD konvertiert Dinge wie Ligaturen in ASCII-Zeichen (z. B. fi zu fi), NFD tut dies nicht.
Brust 8
@ KarolS Ich sehe keine von ihnen mit Akzenten
Eis
@eis Ein Schrägstrich über einem Buchstaben gilt als diakritisch: en.wikipedia.org/wiki/Diacritic Und wenn Sie eine strengere Definition eines "Akzents" wie auf dieser Wikipedia-Seite verwenden, dann ist Diaeresis kein Akzent, also Nicos Antwort ist immer noch falsch.
Karol S
6

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.

NinjaCat
quelle
5
Einverstanden. Zum Beispiel auf Schwedisch: "höra" (hören) -> "hora" (Hure)
Christoffer Hammarström
14
Es ist egal, was sie bedeuten. Die Frage ist, wie man sie entfernt.
Erick Robertson
7
Erick: Es ist wichtig, wie sie heißen. Wenn in der Frage gefragt wird, wie Akzente entfernt werden sollen und ob dies keine Akzente sind, lautet die Antwort möglicherweise nicht nur, wie all diese Dinge entfernt werden sollen, die wie Akzente aussehen. Dies sollte jedoch wahrscheinlich ein Kommentar und keine Antwort sein.
Smig
4
Ich denke, der normale Anwendungsfall hierfür ist die Suche, insbesondere die Suche nach gemischten Sprachen, häufig mit einer englischen Tastatur als Eingabe. In diesem Fall ist es besser, falsch positive als falsch negative Ergebnisse zu erhalten.
Nilskp
3

Ich habe das gleiche Problem im Zusammenhang mit der Überprüfung der Strings-Gleichheit festgestellt. Einer der Vergleichsstrings hat den ASCII-Zeichencode 128-255 .

dh nicht brechender Raum - [Hex - A0] Raum [Hex - 20]. Anzeigen von nicht unterbrechendem Speicherplatz über HTML. Ich habe folgendes verwendet spacing entities. Ihr Charakter und seine Bytes sind wie&emsp is very wide space[ ]{-30, -128, -125}, &ensp is somewhat wide space[ ]{-30, -128, -126}, &thinsp is narrow space[ ]{32} , Non HTML Space {}

String s1 = "My Sample Space Data", s2 = "My Sample Space Data";
System.out.format("S1: %s\n", java.util.Arrays.toString(s1.getBytes()));
System.out.format("S2: %s\n", java.util.Arrays.toString(s2.getBytes()));

Ausgabe in Bytes:

S1: [77, 121, 3283, 97, 109, 112, 108, 101, 3283, 112, 97, 99, 101 32, 68, 97, 116, 97] S2: [77, 121 -30, -128, -125, 83, 97, 109, 112, 108, 101, -30, -128, -12583, 112, 97, 99, 101 -30, -128, -125, 68, 97, 116, 97]

Verwenden Sie den folgenden Code für verschiedene Räume und ihre Byte-Codes: wiki for List_of_Unicode_characters

String spacing_entities = "very wide space,narrow space,regular space,invisible separator";
System.out.println("Space String :"+ spacing_entities);
byte[] byteArray = 
    // spacing_entities.getBytes( Charset.forName("UTF-8") );
    // Charset.forName("UTF-8").encode( s2 ).array();
    {-30, -128, -125, 44, -30, -128, -126, 44, 32, 44, -62, -96};
System.out.println("Bytes:"+ Arrays.toString( byteArray ) );
try {
    System.out.format("Bytes to String[%S] \n ", new String(byteArray, "UTF-8"));
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
}
  • ➩ ASCII-Transliterationen von Unicode-Zeichenfolgen für Java. unidecode

    String initials = Unidecode.decode( s2 );
  • ➩ Verwenden von Guava: Google Core Libraries for Java.

    String replaceFrom = CharMatcher.WHITESPACE.replaceFrom( s2, " " );

    Verwenden Sie für die URL-Codierung für den Speicherplatz die Guava-Bibliothek.

    String encodedString = UrlEscapers.urlFragmentEscaper().escape(inputString);
  • ➩ Um dieses Problem String.replaceAll()bei einigen zu überwinden RegularExpression.

    // \p{Z} or \p{Separator}: any kind of whitespace or invisible separator.
    s2 = s2.replaceAll("\\p{Zs}", " ");
    
    
    s2 = s2.replaceAll("[^\\p{ASCII}]", " ");
    s2 = s2.replaceAll(" ", " ");
  • ➩ 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.

    Geben Sie hier die Bildbeschreibung ein

    s2 = Normalizer.normalize(s2, Normalizer.Form.NFKC);

Testen von Zeichenfolgen und Ausgaben auf verschiedenen Ansätzen wie ➩ Unidecode, Normalizer, StringUtils .

String strUni = "Tĥïŝ ĩš â fůňķŷ Šťŕĭńġ Æ,Ø,Ð,ß";

// This is a funky String AE,O,D,ss
String initials = Unidecode.decode( strUni );

// Following Produce this o/p: Tĥïŝ ĩš â fůňķŷ Šťŕĭńġ Æ,Ø,Ð,ß
String temp = Normalizer.normalize(strUni, Normalizer.Form.NFD);
Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
temp = pattern.matcher(temp).replaceAll("");

String input = org.apache.commons.lang3.StringUtils.stripAccents( strUni );

Die Verwendung von Unidecode ist der best choiceunten gezeigte endgültige Code.

public static void main(String[] args) {
    String s1 = "My Sample Space Data", s2 = "My Sample Space Data";
    String initials = Unidecode.decode( s2 );
    if( s1.equals(s2)) { //[ , ] %A0 - %2C - %20 « http://www.ascii-code.com/
        System.out.println("Equal Unicode Strings");
    } else if( s1.equals( initials ) ) {
        System.out.println("Equal Non Unicode Strings");
    } else {
        System.out.println("Not Equal");
    }

}
Yash
quelle
3

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.

OlgaMaciaszek
quelle
1
Sieht vielversprechend aus, aber ich wünschte, dies wäre ein aktiveres / gepflegtes Projekt und auf Maven verfügbar.
Phil
2

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.

public static String flattenToAscii(String string) {
    char[] out = new char[string.length()];
    String norm = Normalizer.normalize(string, Normalizer.Form.NFD);

    int j = 0;
    for (int i = 0, n = norm.length(); i < n; ++i) {
        char c = norm.charAt(i);
        int type = Character.getType(c);

        //Log.d(TAG,""+c);
        //by Ricardo, modified the character check for accents, ref: http://stackoverflow.com/a/5697575/689223
        if (type != Character.NON_SPACING_MARK){
            out[j] = c;
            j++;
        }
    }
    //Log.d(TAG,"normalized string:"+norm+"/"+new String(out));
    return new String(out);
}
Ricardo Freitas
quelle
1

Eine der besten Möglichkeiten , Regex und Normalizer zu verwenden, wenn Sie keine Bibliothek haben, ist:

    public String flattenToAscii(String s) {
                if(s == null || s.trim().length() == 0)
                        return "";
                return Normalizer.normalize(s, Normalizer.Form.NFD).replaceAll("[\u0300-\u036F]", "");
}

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.

Zhar
quelle
0

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:

Composite Unicode
Precomposed Unicode

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.

In Composite Unicode, "Ồ" is combined from 2 char: Ô (U+00d4) and ̀ (U+0300)
In Precomposed Unicode, "Ồ" is single char (U+1ED2)

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.

Hoang Tran
quelle
-1

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:

   fun stripAccents(s: String):String{

   if (s == null) {
      return "";
   }

val chars: CharArray = s.toCharArray()

var sb = StringBuilder(s)
var cont: Int = 0

while (chars.size > cont) {
    var c: kotlin.Char
    c = chars[cont]
    var c2:String = c.toString()
   //these are my needs, in case you need to convert other accents just Add new entries aqui
    c2 = c2.replace("Ã", "A")
    c2 = c2.replace("Õ", "O")
    c2 = c2.replace("Ç", "C")
    c2 = c2.replace("Á", "A")
    c2 = c2.replace("Ó", "O")
    c2 = c2.replace("Ê", "E")
    c2 = c2.replace("É", "E")
    c2 = c2.replace("Ú", "U")

    c = c2.single()
    sb.setCharAt(cont, c)
    cont++

}

return sb.toString()

}}

Um diesen Spaß zu nutzen, gießen Sie den Code wie folgt:

     var str: String
     str = editText.text.toString() //get the text from EditText
     str = str.toUpperCase().trim()

     str = stripAccents(str) //call the function
Thiago Silva
quelle