Pregunta

El problema es que, como saben, hay miles de caracteres en el gráfico Unicode y quiero convertir todos los caracteres similares a las letras que están en alfabeto inglés.

Por ejemplo, aquí hay algunas conversiones:

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

y vi que hay más de 20 versiones de la letra A / a. y no sé cómo clasificarlos. Parecen agujas en el pajar.

La lista completa de caracteres Unicode está en http: //www.ssec .wisc.edu / ~ tomw / java / unicode.html o http://unicode.org /charts/charindex.html . Solo intenta desplazarte hacia abajo y ver las variaciones de las letras.

¿Cómo puedo convertir todo esto con Java? Por favor, ayúdame :(

¿Fue útil?

Solución

Volver a publicar mi publicación de ¿Cómo lo hago? eliminar diacríticos (acentos) de una cadena en .NET?

Este método funciona bien en Java (con el único fin de eliminar los signos diacríticos, también conocidos como acentos) .

Básicamente, convierte a todos los personajes acentuados en sus equivalentes descentrados seguidos de sus diacríticos combinados. Ahora puedes usar una expresión regular para quitarte los signos diacríticos.

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

Otros consejos

Es parte de Apache Commons Lang a partir de la versión. 3.0.

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

devuelve An

Consulte también http: //www.drillio. com / es / software-development / java / remove-accents-diacritics-in-any-language /

Intentando " convertirlos a todos " Es el enfoque equivocado del problema.

En primer lugar, debe comprender las limitaciones de lo que está tratando de hacer. Como otros han señalado, los signos diacríticos están ahí por una razón: son letras esencialmente únicas en el alfabeto de ese idioma con su propio significado / sonido, etc .: eliminar esas marcas es lo mismo que reemplazar letras al azar en una palabra en inglés. Esto es incluso antes de considerar los idiomas cirílicos y otros textos basados ??en guiones como el árabe, que simplemente no se pueden "convertir". al inglés.

Si debe , por cualquier razón, convertir caracteres, entonces la única forma sensata de abordar esto para reducir en primer lugar el alcance de la tarea en cuestión. Considere la fuente de la entrada, si está codificando una aplicación para "el mundo occidental". (para usar una frase tan buena como cualquiera), sería poco probable que alguna vez necesite analizar los caracteres árabes. Del mismo modo, el conjunto de caracteres Unicode contiene cientos de símbolos matemáticos y gráficos: no hay una forma (fácil) para que los usuarios ingresen directamente estos, por lo que puede suponer que pueden ignorarse.

Al seguir estos pasos lógicos, puede reducir el número de caracteres posibles para analizar hasta el punto en que sea factible una operación de búsqueda / reemplazo basada en el diccionario. Luego se convierte en una pequeña cantidad de trabajo un poco aburrido crear los diccionarios y una tarea trivial para realizar el reemplazo. Si su idioma admite caracteres Unicode nativos (como lo hace Java) y optimiza las estructuras estáticas correctamente, tales hallazgos y reemplazos tienden a ser cegadoramente rápidos.

Esto proviene de la experiencia de haber trabajado en una aplicación que era necesaria para permitir a los usuarios finales buscar datos bibliográficos que incluían caracteres diacríticos. Las matrices de búsqueda (como en nuestro caso) tardaron tal vez 1 día hombre en producirse, para cubrir todas las marcas diacríticas para todos los idiomas de Europa occidental.

Desde la codificación que convierte a "la Familia" en " t?? T ? ? ? ly " es efectivamente aleatorio y no sigue ningún algoritmo que pueda explicarse por la información de los puntos de código Unicode involucrados, no hay una forma general de resolver esto algorítmicamente.

Deberá construir la asignación de caracteres Unicode en caracteres latinos a los que se parecen. Probablemente podría hacer esto con algo de aprendizaje automático inteligente sobre los glifos reales que representan los puntos de código Unicode. Pero creo que el esfuerzo para esto sería mayor que construir manualmente ese mapeo. Especialmente si tiene una buena cantidad de ejemplos a partir de los cuales puede construir su mapeo.

Para aclarar: algunas de las sustituciones pueden resolverse realmente a través de los datos Unicode (como lo demuestran las otras respuestas), pero algunas letras simplemente no tienen una asociación razonable con los caracteres latinos a los que se parecen.

Ejemplos:

  • " ? " (U + 0452 CYRILLIC SMALL LETTER DJE) está más relacionado con " d " que a "h", pero se usa para representar "h".
  • " T " (U + 0166 LETRA T DE CAPITAL LATINA CON CARRERA) está algo relacionado con '' T '' (como su nombre lo indica), pero se usa para representar " F " ;.
  • " ? " (U + 0E04 THAI CHARACTER KHO KHWAI) no está relacionado con ningún carácter latino en absoluto y, en su ejemplo, se utiliza para representar " a "

La solicitud original ya ha sido respondida.

Sin embargo, estoy publicando la respuesta a continuación para aquellos que podrían estar buscando un código genérico de transliteración para transliterar cualquier juego de caracteres al latín / inglés en Java.

Significado ingenuo de tranliteración: La cadena traducida en su forma final / juego de caracteres de destino suena como la cadena en su forma original. Si queremos transliterar cualquier juego de caracteres al latín (alfabetos en inglés), entonces ICU4 (biblioteca ICU4J en Java) hará el trabajo.

Aquí está el fragmento de código en 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;
    }

Si la necesidad es convertir " & # 242; & # 233; & # 305; & # 351; & # 246; & # 231; - > oeisoc " ;, puede usar este un punto de partida:

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

El JDK 1.6 proporciona la clase java.text.Normalizer que se puede usar para esta tarea.

Vea un ejemplo aquí

Cadena probada: & # 193; & # 194; & # 195; & # 196; & # 197; & # 198; & # 199; & # 200; & # 201; & # 202; & # 203; & # 204; & # 205; & # 206; & # 207; & # 208; & # 209; & # 210; & # 211; & # 212; & # 213; & # 214; & # 216; & # 217; & # 218; & # 219; & # 220; & # 221; & # 223;

Probado:

  • Salida de Apache Commons Lang3 : AAAAA & # 198; CEEEEIIII & # 208; NOOOOO & # 216; UUUUY & # 223;
  • Salida de ICU4j : AAAAA & # 198; CEEEEIIII & # 208; NOOOOO & # 216; UUUUY & # 223;
  • Salida de JUnidecode : AAAAAAECEEEEIIIIDNOOOOOOUUUUUss (problema con & # 221; y otro problema )
  • Salida de Unidecode : AAAAAAECEEEEIIIIDNOOOOOOUUUUYss

La última opción es la mejor.

Puede intentar usar unidecode , que está disponible como ruby ??gem y como módulo perl en cpan . Esencialmente, funciona como una gran tabla de búsqueda, donde cada punto de código Unicode se relaciona con un carácter o cadena ascii.

No hay una manera fácil o general de hacer lo que quieres porque es solo tu opinión subjetiva de que estas letras se parecen a las letras latinas a las que deseas convertir. En realidad, son letras separadas con sus propios nombres y sonidos distintos que simplemente parecen superficialmente una letra latina.

Si desea esa conversión, debe crear su propia tabla de traducción basada en las letras latinas a las que cree que deberían convertirse las letras no latinas.

(Si solo desea eliminar las marcas diacritales, hay algunas respuestas en este hilo: ¿Cómo elimino los signos diacríticos (acentos) de una cadena en .NET? Sin embargo, usted describe un problema más general)

Llego tarde a la fiesta, pero después de enfrentar este problema hoy, encontré que esta respuesta es muy buena:

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

Referencia: https://stackoverflow.com/a/16283863

El problema con " convertir " Unicode arbitrario para ASCII es que el significado de un personaje depende de la cultura. Por ejemplo, & # 8220; & # 223; & # 8221; a una persona de habla alemana debe convertirse a "ss" mientras que un angloparlante probablemente lo convertiría a & # 8220; B & # 8221 ;.

Agregue a eso el hecho de que Unicode tiene múltiples puntos de código para los mismos glifos.

El resultado es que la única forma de hacerlo es crear una tabla masiva con cada carácter Unicode y el carácter ASCII al que desea convertirlo. Puede tomar un atajo normalizando caracteres con acentos para normalizar desde KD, pero no todos los caracteres se normalizan a ASCII. Además, Unicode no define qué partes de un glifo son `` acentos ''.

Aquí hay un pequeño extracto de una aplicación que hace esto:

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

La siguiente clase hace el truco:

org.apache.lucene.analysis.miscellaneous.ASCIIFoldingFilter
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top