special leer incombiningdiacriticalmarks characters all acentos accents java string diacritics

leer - normalize accents java



¿Hay alguna forma de deshacerse de los acentos y convertir una cadena completa en letras normales? (9)

A partir de 2011, puede utilizar StringUtils.stripAccents(input) Apache Commons StringUtils.stripAccents(input) (desde la StringUtils.stripAccents(input) 3.0):

String input = StringUtils.stripAccents("Tĥïŝ ĩš â fůňķŷ Šťŕĭńġ"); System.out.println(input); // Prints "This is a funky String"

Nota:

La respuesta aceptada (de Erick Robertson) no funciona para Ø o Ł. Apache Commons 3.5 tampoco funciona para Ø, pero sí funciona para Ł. Después de leer el artículo de Wikipedia para Ø , no estoy seguro de que deba ser reemplazado por "O": es una letra separada en noruego y danés, alfabetizada después de "z". Es un buen ejemplo de las limitaciones del enfoque de "acentos de tira".

¿Hay una mejor manera de deshacerse de los acentos y hacer que esas letras sean regulares, aparte de usar el método String.replaceAll() y reemplazar las letras una por una? Ejemplo:

Entrada: orčpžsíáýd

Salida: orcpzsiayd

No es necesario incluir todas las letras con acentos como el alfabeto ruso o el chino.


Dependiendo del idioma, esos podrían no ser considerados acentos (que cambian el sonido de la letra), sino signos diacríticos.

https://en.wikipedia.org/wiki/Diacritic#Languages_with_letters_containing_diacritics

"Bosnio y croata tienen los símbolos č, ć, đ, š y ž, que se consideran letras separadas y se enumeran como tales en diccionarios y otros contextos en los que las palabras se enumeran según el orden alfabético".

Eliminarlos podría ser cambiar inherentemente el significado de la palabra o cambiar las letras a otras completamente diferentes.


EDITAR: Si no está atascado con Java <6 y la velocidad no es crítica y / o la tabla de traducción es demasiado limitada, use la respuesta de David. El punto es usar el Normalizer (introducido en Java 6) en lugar de la tabla de traducción dentro del bucle.

Si bien esta no es una solución "perfecta", funciona bien cuando conoce el rango (en nuestro caso Latin1,2), funcionó antes de Java 6 (aunque no es un problema real) y es mucho más rápido que la versión más sugerida (puede o no no ser un problema):

/** * Mirror of the unicode table from 00c0 to 017f without diacritics. */ private static final String tab00c0 = "AAAAAAACEEEEIIII" + "DNOOOOO/u00d7/u00d8UUUUYI/u00df" + "aaaaaaaceeeeiiii" + "/u00f0nooooo/u00f7/u00f8uuuuy/u00fey" + "AaAaAaCcCcCcCcDd" + "DdEeEeEeEeEeGgGg" + "GgGgHhHhIiIiIiIi" + "IiJjJjKkkLlLlLlL" + "lLlNnNnNnnNnOoOo" + "OoOoRrRrRrSsSsSs" + "SsTtTtTtUuUuUuUu" + "UuUuWwYyYZzZzZzF"; /** * Returns string without diacritics - 7 bit approximation. * * @param source string to convert * @return corresponding string without diacritics */ public static String removeDiacritic(String source) { char[] vysl = new char[source.length()]; char one; for (int i = 0; i < source.length(); i++) { one = source.charAt(i); if (one >= ''/u00c0'' && one <= ''/u017f'') { one = tab00c0.charAt((int) one - ''/u00c0''); } vysl[i] = one; } return new String(vysl); }

Las pruebas en mi HW con JDK de 32 bits muestran que esto realiza la conversión de àèéľšťč89FDČ a aelstc89FDC 1 millón de veces en ~ 100 ms, mientras que el modo Normalizador lo hace en 3.7 s (37x más lento). En caso de que sus necesidades sean alrededor del rendimiento y usted conozca el rango de entrada, esto puede ser para usted.

Disfruta :-)


He enfrentado el mismo problema relacionado con la verificación de igualdad de cadenas. Una de las cadenas de comparación tiene un código de caracteres ASCII 128-255 .

es decir, espacio sin ruptura - [Hex - A0] Espacio [Hex - 20]. Para mostrar el espacio sin ruptura sobre HTML. He utilizado las siguientes spacing entities . Su carácter y sus bytes son como &emsp is very wide space[ ]{-30, -128, -125}, &ensp is somewhat wide space[ ]{-30, -128, -126}, &thinsp is narrow space[ ]{32} , Non HTML Space {}

String s1 = "My Sample Space Data", s2 = "My Sample Space Data"; System.out.format("S1: %s/n", java.util.Arrays.toString(s1.getBytes())); System.out.format("S2: %s/n", java.util.Arrays.toString(s2.getBytes()));

Salida en bytes:

S1: [77, 121, 32 , 83, 97, 109, 112, 108, 101, 32 , 83, 112, 97, 99, 101, 32 , 68, 97, 116, 97] S2: [77, 121, -30, -128, -125 , 83, 97, 109, 112, 108, 101, -30, -128, -125 , 83, 112, 97, 99, 101, -30, -128, -125 , 68 , 97, 116, 97]

Utilice el código de abajo para diferentes espacios y sus códigos de bytes: wiki for List_of_Unicode_characters

String spacing_entities = "very wide space,narrow space,regular space,invisible separator"; System.out.println("Space String :"+ spacing_entities); byte[] byteArray = // spacing_entities.getBytes( Charset.forName("UTF-8") ); // Charset.forName("UTF-8").encode( s2 ).array(); {-30, -128, -125, 44, -30, -128, -126, 44, 32, 44, -62, -96}; System.out.println("Bytes:"+ Arrays.toString( byteArray ) ); try { System.out.format("Bytes to String[%S] /n ", new String(byteArray, "UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); }

  • Trans Transliteraciones ASCII de la cadena Unicode para Java. unidecode

    String initials = Unidecode.decode( s2 );

  • ➩ usando Guava : Google Core Libraries for Java .

    String replaceFrom = CharMatcher.WHITESPACE.replaceFrom( s2, " " );

    Para la codificación de URL para el espacio utilice la biblioteca de guayaba.

    String encodedString = UrlEscapers.urlFragmentEscaper().escape(inputString);

  • ➩ Para superar este problema, utilice String.replaceAll() con alguna regular-expressions.info .

    // /p{Z} or /p{Separator}: any kind of whitespace or invisible separator. s2 = s2.replaceAll("//p{Zs}", " "); s2 = s2.replaceAll("[^//p{ASCII}]", " "); s2 = s2.replaceAll(" ", " ");

  • java.text.Normalizer.Form Utilizando java.text.Normalizer.Form . Esta enumeración proporciona constantes de las cuatro formas de normalización de Unicode que se describen en el Anexo Nº 15 de la Norma de Unicode - Formas de normalización de Unicode y dos métodos para acceder a ellas.

    s2 = Normalizer.normalize(s2, Normalizer.Form.NFKC);

Prueba de String y salidas en diferentes enfoques como ➩ Unidecode, Normalizer, StringUtils .

String strUni = "Tĥïŝ ĩš â fůňķŷ Šťŕĭńġ Æ,Ø,Ð,ß"; // This is a funky String AE,O,D,ss String initials = Unidecode.decode( strUni ); // Following Produce this o/p: Tĥïŝ ĩš â fůňķŷ Šťŕĭńġ Æ,Ø,Ð,ß String temp = Normalizer.normalize(strUni, Normalizer.Form.NFD); Pattern pattern = Pattern.compile("//p{InCombiningDiacriticalMarks}+"); temp = pattern.matcher(temp).replaceAll(""); String input = org.apache.commons.lang3.StringUtils.stripAccents( strUni );

Usar Unidecode es la best choice , Mi código final se muestra a continuación.

public static void main(String[] args) { String s1 = "My Sample Space Data", s2 = "My Sample Space Data"; String initials = Unidecode.decode( s2 ); if( s1.equals(s2)) { //[ , ] %A0 - %2C - %20 « http://www.ascii-code.com/ System.out.println("Equal Unicode Strings"); } else if( s1.equals( initials ) ) { System.out.println("Equal Non Unicode Strings"); } else { System.out.println("Not Equal"); } }


La solución de @ virgo47 es muy rápida, pero aproximada. La respuesta aceptada utiliza Normalizer y una expresión regular. Me pregunté qué parte del tiempo tardó Normalizer en comparación con la expresión regular, ya que la eliminación de todos los caracteres que no son ASCII se puede hacer sin una expresión regular:

import java.text.Normalizer; public class Strip { public static String flattenToAscii(String string) { StringBuilder sb = new StringBuilder(string.length()); string = Normalizer.normalize(string, Normalizer.Form.NFD); for (char c : string.toCharArray()) { if (c <= ''/u007F'') sb.append(c); } return sb.toString(); } }

Se pueden obtener pequeños incrementos de velocidad adicionales escribiendo en un char [] y no llamando aCharArray (), aunque no estoy seguro de que la disminución en la claridad del código lo amerite:

public static String flattenToAscii(String string) { char[] out = new char[string.length()]; string = Normalizer.normalize(string, Normalizer.Form.NFD); int j = 0; for (int i = 0, n = string.length(); i < n; ++i) { char c = string.charAt(i); if (c <= ''/u007F'') out[j++] = c; } return new String(out); }

Esta variación tiene la ventaja de la corrección de la que usa Normalizer y parte de la velocidad de la que usa una tabla. En mi máquina, esta es aproximadamente 4 veces más rápida que la respuesta aceptada, y de 6.6x a 7x más lenta que la de @ virgo47 (la respuesta aceptada es aproximadamente 26x más lenta que la de @ virgo47 en mi máquina).


La solución de @David Conrad es la más rápida que probé con el Normalizador, pero tiene un error. Básicamente, se eliminan los caracteres que no son acentos, por ejemplo, los caracteres chinos y otras letras como æ. Los caracteres que queremos eliminar son marcas sin espacios, caracteres que no ocupan un ancho adicional en la cadena final. Estos caracteres de ancho cero básicamente se combinan en algún otro carácter. Si puedes verlos aislados como un personaje, por ejemplo como este `, supongo que se combina con el carácter de espacio.

public static String flattenToAscii(String string) { char[] out = new char[string.length()]; String norm = Normalizer.normalize(string, Normalizer.Form.NFD); int j = 0; for (int i = 0, n = norm.length(); i < n; ++i) { char c = norm.charAt(i); int type = Character.getType(c); //Log.d(TAG,""+c); //by Ricardo, modified the character check for accents, ref: http://.com/a/5697575/689223 if (type != Character.NON_SPACING_MARK){ out[j] = c; j++; } } //Log.d(TAG,"normalized string:"+norm+"/"+new String(out)); return new String(out); }


Sugiero Junidecode . No solo manejará ''Ł'' y ''Ø'', sino que también funciona bien para transcribir de otros alfabetos, como el chino, al alfabeto latino.


Usa java.text.Normalizer para manejar esto por ti.

string = Normalizer.normalize(string, Normalizer.Form.NFD);

Esto separará todas las marcas de acento de los personajes. Entonces, solo necesitas comparar cada personaje contra una letra y tirar los que no lo son.

string = string.replaceAll("[^//p{ASCII}]", "");

Si su texto está en Unicode, debe usar esto en su lugar:

string = string.replaceAll("//p{M}", "");

Para unicode, //P{M} coincide con el glifo base y //p{M} (en minúsculas) coincide con cada acento.

Gracias a GarretWilson por el puntero y regular-expressions.info por la gran guía de Unicode.


System.out.println(Normalizer.normalize("àèé", Normalizer.Form.NFD).replaceAll("//p{InCombiningDiacriticalMarks}+", ""));

trabajó para mi. La salida del fragmento de código anterior da "aee", que es lo que quería, pero

System.out.println(Normalizer.normalize("àèé", Normalizer.Form.NFD).replaceAll("[^//p{ASCII}]", ""));

No hice ninguna sustitución.