mostrar codificacion acentos java unicode special-characters diacritics

java - codificacion - ã³



Conversión de símbolos, letras de acento al alfabeto inglés (12)

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. Se ven como 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 letras.

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


Cadena probada: ÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÙÔÕÚØÙÚÛÜÝß

Probado:

  • Salida de Apache Commons Lang3 : AAAAAÆCEEEEIIIIÐNOOOOOØUUUUYß
  • Salida de ICU4j : AAAAAÆCEEEEIIIIÐNOOOOOØUUUUYß
  • Salida de JUnidecode : AAAAAAECEEEEIIIIDNOOOOOOUUUUUss (problema con Ý y otro issue )
  • Salida de Unidecode : AAAAAAECEEEEIIIIDNOOOOOOUUUUYss

La última elección es la mejor.


Como la codificación que convierte a "la Familia" en "tђє Ŧ เ 3 เ "y" es efectivamente aleatoria 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.

Tendrá que crear la asignación de caracteres Unicode en caracteres latinos a los que se parecen. Probablemente puedas hacer esto con algunos Smart Machine Learning en los glifos reales que representan los puntos de código Unicode. Pero creo que el esfuerzo para esto sería mayor que la creación manual de 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 en realidad se pueden resolver a través de los datos Unicode (como 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 con "h", pero se usa para representar "h".
  • "Ŧ" (U + 0166 LETRA MAYÚSCULA LATINA T CON STROKE) está algo relacionada con "T" (como su nombre indica), pero se usa para representar "F".
  • "ค" (U + 0E04 THAI CHARACTER KHO KHWAI) no está relacionado con ningún carácter latino y en su ejemplo se usa para representar "a"

El problema de "convertir" Unicode arbitrario en ASCII es que el significado de un personaje depende de la cultura. Por ejemplo, "ß" para una persona de habla alemana debería convertirse a "ss", mientras que un hablante de inglés probablemente la convertiría en "B".

A esto se añade 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 desee convertirlo. Puede tomar un atajo normalizando caracteres con acentos a la normalización de KD, pero no todos los caracteres se normalizan en 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... }



Intentar "convertirlos a todos" es un 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 esencialmente letras ú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 antes de considerar los lenguajes 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 es 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 cualquier otra), es poco probable que alguna vez necesite analizar caracteres árabes. Del mismo modo, el juego de caracteres Unicode contiene cientos de símbolos matemáticos y gráficos: no hay una forma (fácil) de que los usuarios los ingresen directamente, por lo que puede suponer que se pueden ignorar.

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

Esto proviene de la experiencia de haber trabajado en una aplicación que era necesaria para permitir que los usuarios finales busquen datos bibliográficos que incluyan caracteres diacríticos. Los arreglos de búsqueda (como lo fue en nuestro caso) tomaron tal vez 1 día para producir, para cubrir todas las marcas diacríticas de todos los idiomas de Europa occidental.


La siguiente clase hace el truco:

org.apache.lucene.analysis.miscellaneous.ASCIIFoldingFilter


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 de transliteración genérico para transcribir cualquier charset en latín / inglés en Java.

Significado ingenuo de la transliteración: la secuencia traducida en su forma final / conjunto de caracteres objetivo suena como la cadena en su forma original. Si queremos transcribir cualquier charset al latín (alfabetos ingleses), 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; }


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://.com/a/16283863


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

Si desea esa conversión, debe crear su propia tabla de traducción en función de las letras latinas en las que cree que deben convertirse las letras que no sean latinas.

(Si solo desea eliminar las marcas diacríticas, 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)


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


Reposicionando mi publicación de ¿Cómo elimino los signos diacríticos (acentos) de una cadena en .NET?

Este método funciona bien en Java (con el único propósito de eliminar marcas diacríticas, también conocidas como acentos) .

Básicamente convierte todos los caracteres acentuados en sus contrapartes deAccented seguidas de sus signos diacríticos combinados. Ahora puede usar una expresión regular para quitar 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(""); }


Si es necesario convertir "òéışöç-> oeisoc", puede usar esto como 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 here