Преобразование символов, акцентированных букв на английский алфавит

Проблема в том, что, как вы знаете, в диаграмме Unicode есть тысячи символов, и я хочу преобразовать все похожие символы в буквы, которые находятся на английском алфавите.

Например, здесь представлено несколько преобразований:

ҥ->H Ѷ->V Ȳ->Y Ǭ->O Ƈ->C tђє Ŧค๓เℓy --> the Family ... 

и я увидел, что существует более 20 версий буквы A / a. и я не знаю, как их classифицировать. Они выглядят как иголки в стоге сена.

Полный список символов Unicode находится по адресу http://www.ssec.wisc.edu/~tomw/java/unicode.html или http://unicode.org/charts/charindex.html . Просто попробуйте прокрутить вниз и увидеть варианты букв.

Как я могу преобразовать все это с помощью Java? Пожалуйста, помогите мне 🙁

12 Solutions collect form web for “Преобразование символов, акцентированных букв на английский алфавит”

Отправка моего сообщения из Как удалить диакритические знаки (акценты) из строки в .NET?

Этот метод отлично работает в java (исключительно для удаления диакритических знаков aka accents) .

Он в основном преобразует всех акцентированных персонажей в их де-амбиентные коллеги, а затем их комбинированные диакритики. Теперь вы можете использовать регулярное выражение для удаления диакритики.

 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(""); } 

Это часть Apache Commons Lang от версии. 3.0.

 org.apache.commons.lang3.StringUtils.stripAccents("Añ"); 

возвращает

Также см. http://www.drillio.com/ru/software-development/java/removing-accents-diacritics-in-any-language/

Попытка «преобразовать их всех» – неправильный подход к проблеме.

Во-первых, вам нужно понять ограничения того, что вы пытаетесь сделать. Как указывали другие, диакритики существуют по какой-то причине: они по сути являются уникальными буквами в алфавите этого языка с их собственным значением / звуком и т. Д .: удаление этих меток точно так же, как замена случайных букв английским словом. Это прежде, чем вы даже перейдете к рассмотрению кириллических языков и других текстов на основе скриптов, таких как арабский, которые просто не могут быть «преобразованы» на английский.

Если по какой-либо причине вы должны конвертировать символы, то это единственный разумный способ приблизиться к этому, чтобы сначала уменьшить объем задачи. Рассмотрим источник ввода – если вы кодируете приложение для «западного мира» (использовать как хорошую фразу как любой), вряд ли вам понадобится проанализировать арабские символы. Аналогично, набор символов Unicode содержит сотни математических и графических символов: нет (простого) способа для пользователей напрямую вводить их, поэтому вы можете предположить, что их можно игнорировать.

Принимая эти логические шаги, вы можете уменьшить количество возможных символов для синтаксического анализа до точки, в которой операция поиска и замены на основе словаря возможна. Затем это становится небольшим количеством немного скучной работы, создающей словари, и тривиальной задачей для выполнения замены. Если ваш язык поддерживает родные символы Unicode (как это делает Java) и оптимизирует статические структуры правильно, такие нахождение и замещения имеют тенденцию быть ослепительно быстрыми.

Это связано с опытом работы над приложением, которое должно было позволить конечным пользователям выполнять поиск библиографических данных, содержащих диакритические символы. Массивы поиска (как это было в нашем случае) заняли, возможно, 1 человеко-день для производства, чтобы охватить все диакритические знаки для всех западноевропейских языков.

Поскольку кодирование, которое превращает «Семейство» в «tђє Ŧ ค 3 เ ℓy», является случайным и не следует никакому алгоритму, который может быть объяснен информацией о кодовых точках Unicode, нет общего способа решения этой проблемы алгоритмически.

Вам нужно будет построить отображение символов Юникода в латинские символы, которые они напоминают. Вероятно, вы могли бы сделать это с помощью некоторых интеллектуальных машин, изучающих фактические глифы, представляющие кодовые страницы Unicode. Но я думаю, что усилия для этого будут больше, чем вручную создавать это сопоставление. Особенно, если у вас есть много примеров, из которых вы можете построить свое сопоставление.

Чтобы пояснить: некоторые из подстановок действительно могут быть решены с помощью данных Unicode (как показывают другие ответы), но некоторые буквы просто не имеют разумной связи с латинскими символами, которые они напоминают.

Примеры:

  • «ђ» (U + 0452 CYRILLIC SMALL LETTER DJE) больше связано с «d», чем с «h», но используется для представления «h».
  • «Ŧ» (U + 0166 LATIN CAPITAL LETTER T WITH STROKE) несколько связано с «T» (как следует из названия), но используется для представления «F».
  • «ค» (U + 0E04 THAI CHARACTER KHO KHWAI) вообще не связан ни с одним латинским персонажем, а в вашем примере используется для обозначения «a»,

На исходный запрос уже был дан ответ.

Тем не менее, я отправляю ниже ответ для тех, кто может искать общий код транслитерации, чтобы транслитерировать любую кодировку на латинский / английский язык на Java.

Наивное значение транслитерации: переведенная строка в финальной форме / целевой кодировке звучит как строка в оригинальной форме. Если мы хотим транслитерировать любую кодировку на латинский (английские алфавиты), тогда ICU4 (библиотека ICU4J в java) выполнит эту работу.

Вот fragment кода в 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; } 

Если необходимо преобразовать «òéışöç-> oeisoc», вы можете использовать это отправную точку:

 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 предоставляет class java.text.Normalizer, который можно использовать для этой задачи.

См. Пример здесь

Проверенная строка: ÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÜÚÛÜÝß

Протестировано:

  • Выход из Apache Commons Lang3 : AAAAAÆCEEEEIIIIÐNOOOOOØUUUUYß
  • Выход из ICU4j : AAAAAÆCEEEEIIIIÐNOOOOOØUUUUYß
  • Выход из JUnidecode : AAAAAAECEEEEIIIIDNOOOOOOUUUUUss (проблема с Ý и другая проблема )
  • Выход из Unidecode : AAAAAAECEEEEIIIIDNOOOOOOUUUUYss

Последний выбор – лучший.

Вы можете попробовать использовать unidecode , который доступен как rubyовый жемчуг и как perl-модуль на cpan . По сути, он работает как огромная таблица поиска, где каждая точка кода юникода относится к символу или строке ascii.

Существует не простой или общий способ делать то, что вы хотите, потому что это просто ваше субъективное мнение, что эти письма выглядят латинскими буквами, которые вы хотите преобразовать. Они на самом деле являются отдельными буквами с их собственными именами и звуками, которые просто внешне кажутся латинскими буквами.

Если вы хотите это преобразование, вам нужно создать свою собственную таблицу переводов на основе того, какие латинские буквы, по вашему мнению, должны быть преобразованы в нелатинские буквы.

(Если вы хотите удалить диакритические знаки, в этом streamе есть несколько ответов: Как удалить диакритические знаки (акценты) из строки в .NET? Однако вы описываете более общую проблему)

Я опаздываю на вечеринку, но сегодня, столкнувшись с этим вопросом, я нашел этот ответ очень хорошим:

 String asciiName = Normalizer.normalize(unicodeName, Normalizer.Form.NFD) .replaceAll("[^\\p{ASCII}]", ""); 

Ссылка: https://stackoverflow.com/a/16283863

Проблема с «преобразованием» произвольного Unicode в ASCII заключается в том, что значение персонажа зависит от культуры. Например, «ß» для говорящего на немецком языке человека следует преобразовать в «ss», в то время как английский-говорящий, вероятно, преобразует его в «B».

Добавьте к этому тот факт, что Unicode имеет несколько кодовых точек для одних и тех же глифов.

Результатом является то, что единственный способ сделать это – создать массивную таблицу с каждым символом Юникода и символом ASCII, в который вы хотите преобразовать его. Вы можете использовать ярлык, нормализуя символы с акцентами до формы нормализации KD, но не все символы нормализуются до ASCII. Кроме того, Unicode не определяет, какие части глифа являются «акцентами».

Вот небольшая выдержка из приложения, которая делает это:

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

Следующий class делает трюк:

 org.apache.lucene.analysis.miscellaneous.ASCIIFoldingFilter 
  • Каковы HTML и XML, специальные символы?
  • Как добавить символ маркера в TextView?
  • Каковы допустимые символы в субдомене?
  • Давайте будем гением компьютера.