Преобразование символов, букв Accent в английский алфавит - PullRequest
123 голосов
/ 17 июня 2009

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

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

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

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

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

Как я могу конвертировать все это с Java? Пожалуйста, помогите мне: (

Ответы [ 12 ]

192 голосов
/ 01 августа 2009

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

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

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

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("");
}
70 голосов
/ 03 ноября 2012

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

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

возвращает An

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

19 голосов
/ 18 июня 2009

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

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

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

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

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

16 голосов
/ 09 сентября 2009

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

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

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

Примеры:

  • «ђ» (U + 0452 КИРИЛЛИЧЕСКОЕ МАЛЕНЬКОЕ ПИСЬМО DJE) больше относится к «d», чем к «h», но используется для обозначения «h».
  • «Ŧ» (U + 0166 LATIN CAPITAL LETTER T WITH STROKE) в некоторой степени связано с «T» (как следует из названия), но используется для обозначения «F».
  • "ค" (U + 0E04 THAI CHARACTER KHO KHWAI) вообще не имеет отношения к какому-либо латинскому символу и в вашем примере используется для обозначения "a"
7 голосов
/ 10 ноября 2014

Исходный запрос уже получен.

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

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

Вот фрагмент кода в 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;
    }
6 голосов
/ 12 апреля 2017

Струнные испытания: ÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝß

Проверено:

Последний вариант самый лучший.

6 голосов
/ 18 июня 2009

Если вам нужно конвертировать "òéışöç-> 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 предоставляет класс java.text.Normalizer, который можно использовать для этой задачи.

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

4 голосов
/ 15 августа 2016

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

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

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

4 голосов
/ 27 июня 2009

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

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

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

4 голосов
/ 17 июня 2009

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

...