Problem polega na tym, że jak wiesz, na wykresie Unicode są tysiące znaków i chcę zamienić wszystkie podobne znaki na litery, które są w alfabecie angielskim.
Na przykład oto kilka konwersji:
ҥ->H
Ѷ->V
Ȳ->Y
Ǭ->O
Ƈ->C
tђє Ŧค๓เℓy --> the Family
...
i zobaczyłem, że istnieje ponad 20 wersji litery A / a. i nie wiem, jak je sklasyfikować. Wyglądają jak igły w stogu siana.
Pełna lista znaków Unicode znajduje się pod adresem http://www.ssec.wisc.edu/~tomw/java/unicode.html lub http://unicode.org/charts/charindex.html . Po prostu spróbuj przewinąć w dół i zobaczyć odmiany liter.
Jak mogę to wszystko przekonwertować za pomocą Java? Proszę pomóż mi :(
java
unicode
special-characters
diacritics
AhmetB - Google
źródło
źródło
Odpowiedzi:
Ponowne publikowanie mojego posta z Jak usunąć znaki diakrytyczne (akcenty) z ciągu znaków w .NET?
Ta metoda działa dobrze w Javie (wyłącznie w celu usunięcia znaków diakrytycznych, czyli aka) .
Zasadniczo konwertuje wszystkie akcentowane znaki na ich pozbawione akcentów odpowiedniki, a następnie ich łączące znaki diakrytyczne. Teraz możesz użyć wyrażenia regularnego, aby usunąć znaki diakrytyczne.
import java.text.Normalizer; import java.util.regex.Pattern; public String deAccent(String str) { String nfdNormalizedString = Normalizer.normalize(str, Normalizer.Form.NFD); Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); return pattern.matcher(nfdNormalizedString).replaceAll(""); }
źródło
Jest częścią Apache Commons Lang od wer. 3.0.
org.apache.commons.lang3.StringUtils.stripAccents("Añ");
zwroty
An
Zobacz także http://www.drillio.com/en/software-development/java/removing-accents-diacritics-in-any-language/
źródło
Próba „przekonwertowania ich wszystkich” jest niewłaściwym podejściem do problemu.
Po pierwsze, musisz zrozumieć ograniczenia tego, co próbujesz zrobić. Jak inni zauważyli, znaki diakrytyczne istnieją z jakiegoś powodu: są to zasadniczo unikalne litery w alfabecie tego języka z własnym znaczeniem / dźwiękiem itp.: Usuwanie tych znaków jest tym samym, co zastępowanie przypadkowych liter w angielskim słowie. To jest jeszcze zanim przejdziesz do rozważenia języków cyrylicy i innych tekstów opartych na pismach, takich jak arabski, których po prostu nie da się „przekonwertować” na angielski.
Jeśli z jakiegoś powodu musisz przekonwertować postacie, to jedyny rozsądny sposób podejścia do tego, aby najpierw zmniejszyć zakres wykonywanego zadania. Weź pod uwagę źródło danych wejściowych - jeśli kodujesz aplikację dla „świata zachodniego” (aby użyć tak dobrego wyrażenia, jak inne), byłoby mało prawdopodobne, że kiedykolwiek będziesz musiał analizować znaki arabskie. Podobnie zestaw znaków Unicode zawiera setki symboli matematycznych i obrazkowych: nie ma (łatwego) sposobu, aby użytkownicy mogli je bezpośrednio wprowadzić, więc można założyć, że można je zignorować.
Wykonując te logiczne kroki, można zmniejszyć liczbę możliwych znaków do przeanalizowania do punktu, w którym operacja wyszukiwania / zamiany w oparciu o słownik jest wykonalna. Tworzenie słowników staje się wtedy niewielką ilością nieco nudnej pracy, a ich zastąpienie staje się banalnym zadaniem. Jeśli twój język obsługuje natywne znaki Unicode (tak jak Java) i poprawnie optymalizuje struktury statyczne, takie wyszukiwanie i zamiany są zwykle niezwykle szybkie.
Wynika to z doświadczenia związanego z pracą nad aplikacją, która była wymagana, aby umożliwić użytkownikom końcowym wyszukiwanie danych bibliograficznych zawierających znaki diakrytyczne. Stworzenie tablic wyszukiwania (tak jak to było w naszym przypadku) zajęło około 1 osobodni, aby pokryć wszystkie znaki diakrytyczne dla wszystkich języków zachodnioeuropejskich.
źródło
Ponieważ kodowanie, które zamienia „rodzinę” na „tђє Ŧ ค ๓ เ ℓy” jest w rzeczywistości losowe i nie jest zgodne z żadnym algorytmem, który można wyjaśnić na podstawie informacji o zawartych w nim punktach kodowych Unicode, nie ma ogólnego sposobu rozwiązania tego algorytmu.
Będziesz musiał zbudować mapowanie znaków Unicode na znaki łacińskie, które przypominają. Prawdopodobnie możesz to zrobić za pomocą inteligentnego uczenia maszynowego na rzeczywistych glifach reprezentujących punkty kodowe Unicode. Myślę jednak, że wysiłek związany z tym byłby większy niż ręczne tworzenie tego mapowania. Zwłaszcza jeśli masz dużą liczbę przykładów, z których możesz zbudować swoje mapowanie.
Dla wyjaśnienia: kilka podstawień można faktycznie rozwiązać za pomocą danych Unicode (jak pokazują inne odpowiedzi), ale niektóre litery po prostu nie mają rozsądnego związku z łacińskimi znakami, które przypominają.
Przykłady:
źródło
Odpowiedź na pierwotną prośbę została już udzielona.
Jednak zamieszczam poniższą odpowiedź dla tych, którzy mogą szukać ogólnego kodu transliteracji do transliteracji dowolnego zestawu znaków na łacinę / angielski w Javie.
Naiwne znaczenie tranliteracji: przetłumaczony ciąg w swojej ostatecznej formie / docelowym zestawie znaków brzmi jak ciąg w swojej oryginalnej formie. Jeśli chcemy dokonać transliteracji dowolnego zestawu znaków na łacinę (alfabety angielskie), wtedy ICU4 (biblioteka ICU4J w java) zrobi to.
Oto fragment kodu w java:
import com.ibm.icu.text.Transliterator; //ICU4J library import public static String TRANSLITERATE_ID = "NFD; Any-Latin; NFC"; public static String NORMALIZE_ID = "NFD; [:Nonspacing Mark:] Remove; NFC"; /** * Returns the transliterated string to convert any charset to latin. */ public static String transliterate(String input) { Transliterator transliterator = Transliterator.getInstance(TRANSLITERATE_ID + "; " + NORMALIZE_ID); String result = transliterator.transliterate(input); return result; }
źródło
Testowane na strunach: ÁÂÃĘÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝß
Przetestowano:
Ostatni wybór jest najlepszy.
źródło
Jeśli potrzebujesz przekonwertować „òéışöç-> oeisoc”, możesz użyć tego jako punktu wyjścia:
public class AsciiUtils { private static final String PLAIN_ASCII = "AaEeIiOoUu" // grave + "AaEeIiOoUuYy" // acute + "AaEeIiOoUuYy" // circumflex + "AaOoNn" // tilde + "AaEeIiOoUuYy" // umlaut + "Aa" // ring + "Cc" // cedilla + "OoUu" // double acute ; private static final String UNICODE = "\u00C0\u00E0\u00C8\u00E8\u00CC\u00EC\u00D2\u00F2\u00D9\u00F9" + "\u00C1\u00E1\u00C9\u00E9\u00CD\u00ED\u00D3\u00F3\u00DA\u00FA\u00DD\u00FD" + "\u00C2\u00E2\u00CA\u00EA\u00CE\u00EE\u00D4\u00F4\u00DB\u00FB\u0176\u0177" + "\u00C3\u00E3\u00D5\u00F5\u00D1\u00F1" + "\u00C4\u00E4\u00CB\u00EB\u00CF\u00EF\u00D6\u00F6\u00DC\u00FC\u0178\u00FF" + "\u00C5\u00E5" + "\u00C7\u00E7" + "\u0150\u0151\u0170\u0171" ; // private constructor, can't be instanciated! private AsciiUtils() { } // remove accentued from a string and replace with ascii equivalent public static String convertNonAscii(String s) { if (s == null) return null; StringBuilder sb = new StringBuilder(); int n = s.length(); for (int i = 0; i < n; i++) { char c = s.charAt(i); int pos = UNICODE.indexOf(c); if (pos > -1){ sb.append(PLAIN_ASCII.charAt(pos)); } else { sb.append(c); } } return sb.toString(); } public static void main(String args[]) { String s = "The result : È,É,Ê,Ë,Û,Ù,Ï,Î,À,Â,Ô,è,é,ê,ë,û,ù,ï,î,à,â,ô,ç"; System.out.println(AsciiUtils.convertNonAscii(s)); // output : // The result : E,E,E,E,U,U,I,I,A,A,O,e,e,e,e,u,u,i,i,a,a,o,c } }
JDK 1.6 udostępnia klasę java.text.Normalizer, której można użyć do tego zadania.
Zobacz przykład tutaj
źródło
Możesz spróbować użyć
unidecode
, który jest dostępny jako rubinowy klejnot i jako moduł perla na cpan . Zasadniczo działa jako ogromna tabela wyszukiwania, w której każdy punkt kodu Unicode odnosi się do znaku lub ciągu znaków ascii.źródło
Nie ma łatwego ani ogólnego sposobu na zrobienie tego, co chcesz, ponieważ jest to tylko twoja subiektywna opinia, że te litery wyglądają tak, jak litery łacińskie, na które chcesz przekonwertować. W rzeczywistości są to oddzielne litery z własnymi, odrębnymi nazwami i dźwiękami, które po prostu wyglądają jak litera łacińska.
Jeśli chcesz tej konwersji, musisz utworzyć własną tabelę tłumaczeń na podstawie tego, na jakie litery łacińskie powinny zostać przekonwertowane litery niełacińskie.
(Jeśli chcesz usunąć tylko znaki diakrytyczne, w tym wątku jest kilka odpowiedzi: Jak usunąć znaki diakrytyczne (akcenty) z ciągu znaków w .NET? Jednak opisujesz bardziej ogólny problem)
źródło
Spóźniłem się na imprezę, ale po dzisiejszym zmierzeniu się z tym problemem uznałem, że ta odpowiedź jest bardzo dobra:
String asciiName = Normalizer.normalize(unicodeName, Normalizer.Form.NFD) .replaceAll("[^\\p{ASCII}]", "");
Źródła: https://stackoverflow.com/a/16283863
źródło
Problem z „konwersją” dowolnego Unicode do ASCII polega na tym, że znaczenie znaku jest zależne od kultury. Na przykład „ß” na osobę niemieckojęzyczną powinno zostać zamienione na „ss”, podczas gdy osoba anglojęzyczna prawdopodobnie zamieniłaby to na „B”.
Dodaj do tego fakt, że Unicode ma wiele punktów kodowych dla tych samych glifów.
W rezultacie jedynym sposobem na to jest utworzenie ogromnej tabeli z każdym znakiem Unicode i znakiem ASCII, na który chcesz go przekonwertować. Możesz skorzystać z skrótu, normalizując znaki z akcentami do normalizacji z KD, ale nie wszystkie znaki normalizują się do ASCII. Ponadto Unicode nie definiuje, które części glifu są „akcentami”.
Oto mały fragment aplikacji, która to robi:
switch (c) { case 'A': case '\u00C0': // À LATIN CAPITAL LETTER A WITH GRAVE case '\u00C1': // Á LATIN CAPITAL LETTER A WITH ACUTE case '\u00C2': // Â LATIN CAPITAL LETTER A WITH CIRCUMFLEX // and so on for about 20 lines... return "A"; break; case '\u00C6':// Æ LATIN CAPITAL LIGATURE AE return "AE"; break; // And so on for pages... }
źródło
Następująca klasa załatwia sprawę:
źródło