Вопрос по unicode, java – Преобразование символов, букв Accent в английский алфавит

123

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

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

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

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

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

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

Этот разговор был сделан раньше - см. @Schnaader выше. dkretz
почему ты хочешь сделать это? Если бы мы знали, какова ваша общая цель, мы могли бы быть более полезными. David Thornley
Если ваш третий пример будет & # x232; & # X2192; Y? Dour High Arch
Дэвид, ты знаешь, что некоторые эмо используют разные символы в предложениях. Вот вам пример: & # xE2C;. & # XA2 ;. т & # x452; & # x454; & # XE2C; & # xE22; & # x3B7; & # x2202; & # x454; & # x433; & # XA2; & # xE04; & # x5E7; & # x452; & # x166; & # xE04; & # xE53; & # xE40; & # x2113; y & lt; - Решите это :) @schnaader, я думаю, это то, что я ищу, но не в Java. AhmetB - Google
Смотрите этот вопрос:stackoverflow.com/questions/249087/… - должны также быть некоторые другие вопросы по этой теме, но я не могу найти их в данный момент. schnaader

Ваш Ответ

12   ответов
2

org.apache.lucene.analysis.miscellaneous.ASCIIFoldingFilter
4

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

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

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

Круто, спасибо :)
А также & # xC6; ... К плохому.
Небольшое предупреждение - он удаляет U + 00DF LATIN SMALL LETTER SHARP S & quot; & # xDF; & quot;
4

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

Error: User Rate Limit ExceededunidecodeError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded AhmetB - Google
4

я в том, что значение символа зависит от культуры. Например, & # x201C; & # xDF; & # x201D; для говорящего по-немецки человека должен быть преобразован в "ss" в то время как носитель английского языка, вероятно, конвертирует его в & # x201C; B & # x201D ;.

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

В результате единственный способ сделать это - создать массивную таблицу с каждым символом 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...
}
190

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

Этот метод отлично работает в Java(purely for the purpose of removing diacritical marks 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("");
}
@ Спасибо за это! Надеюсь это работает :) AhmetB - Google
Error: User Rate Limit Exceeded
\\ p {IsM} не работает для испанских акцентов, таких как & # xE1; & # XF3; & # XFA; & # XF1; & # XE9; & # XED; , Напротив, & quot; \\ p {InCombiningDiacriticalMarks} + хорошо работает для этого
InCombiningDiacriticalMarks не преобразует всю кириллицу. Например, & # x41E; & # x43F; & # x448; & # x442; & # x438; & # x43D; & # x430; & # X411; & # x43E; & # x433; & # x43E; & # x43C; & # x438; & # x43B; & # X430; нетронутым Было бы хорошо, если бы можно было преобразовать его в Опстину Богомилу или что-то
Джордж написал, что было бы лучше использовать \\ p {IsM} вместо \\ p {InCombiningDiacriticalMarks} вglaforge.appspot.com/article/… Обратите внимание, что я не проверял это.
7

Тем не менее, я публикую нижеприведенный ответ для тех, кто может искать общий код транслитерации для транслитерации любого набора символов на латынь / английский в 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;
    }
Error: User Rate Limit Exceeded
6

& # xC2; & # xC3; & # xC4; & # xC5; & # xC6; & # xC7; & # xC8; & # xC9; & # xCA; & # xCB; & # xCB; & # xCC ; & # XCD; & # xCE; & # XCF; & # xD0; & # xd1; & # XD2; & # XD3; & # xD4; & # xd5; & # xD6; & # xD8; & # xD9; & #xDA; & # XDB; & # XDc; & # XDD; & # XDF;

Проверено:

Output from Apache Commons Lang3 : AAAAAÆCEEEEIIIIÐNOOOOOØUUUUYß Output from ICU4j : AAAAAÆCEEEEIIIIÐNOOOOOØUUUUYß Output from JUnidecode : AAAAAAECEEEEIIIIDNOOOOOOUUUUUss (problem with Ý and another issue) Output from Unidecode : AAAAAAECEEEEIIIIDNOOOOOOUUUUYss

The last choice is the best.

Error: User Rate Limit Exceededgithub.com/xuender/unidecodeError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
16

t & # x452; & # x454; & # X166; & # xE04; & # xE53; & # xE40; & # x2113; у & Quot; является фактически случайным и не следует ни одному алгоритму, который может быть объяснен информацией задействованных кодовых точек Unicode, не существует общего способа решить это алгоритмически.

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

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

Примеры:

"ђ" (U+0452 CYRILLIC SMALL LETTER DJE) is more related to "d" than to "h", but is used to represent "h". "Ŧ" (U+0166 LATIN CAPITAL LETTER T WITH STROKE) is somewhat related to "T" (as the name suggests) but is used to represent "F". "ค" (U+0E04 THAI CHARACTER KHO KHWAI) is not related to any latin character at all and in your example is used to represent "a"
19

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

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

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

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

Error: User Rate Limit Exceeded AhmetB - Google
4

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

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

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

Error: User Rate Limit Exceededstackoverflow.com/questions/1016955/…Error: User Rate Limit Exceeded
70

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/

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Единственный, который работал на меня.
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
6

& # xE9; & # x131; & # x15F; & # xF6; & # xE7; & gt; oeisoc & quot ;, вы можете использовать эту отправную точку:

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

См примерВот

Error: User Rate Limit Exceeded AhmetB - Google
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded

Похожие вопросы