8 09
11
2010

Eliminar acentos y caracteres especiales en Java

En ocasiones nos puede resultar útil eliminar de una cadena de texto caracteres especiales, acentos o diacríticos (tíldes, diéresis, eñes, cedillas, etc).

Por ejemplo, en algunos sistemas de reservas aéreas o GDSs, como es el caso de Amadeus, necesitamos limpiar todos los textos que hacen referencia a nombres de pasajeros, direcciones y demás, de aquellos caracteres especiales no soportados por el sistema.

Vamos a ver 2 formas diferentes de eliminar estos caracteres especiales y acentos con 2 técnicas distintas:

1. Reemplazando cadenas de caracteres

    /**
     * Función que elimina acentos y caracteres especiales de
     * una cadena de texto.
     * @param input
     * @return cadena de texto limpia de acentos y caracteres especiales.
     */
    public static String remove1(String input) {
        // Cadena de caracteres original a sustituir.
        String original = "áàäéèëíìïóòöúùuñÁÀÄÉÈËÍÌÏÓÒÖÚÙÜÑçÇ";
        // Cadena de caracteres ASCII que reemplazarán los originales.
        String ascii = "aaaeeeiiiooouuunAAAEEEIIIOOOUUUNcC";
        String output = input;
        for (int i=0; i<original.length(); i++) {
            // Reemplazamos los caracteres especiales.
            output = output.replace(original.charAt(i), ascii.charAt(i));
        }//for i
        return output;
    }//remove1

2. Normalización Unicode. Descomposición canónica

Partamos en primer lugar del hecho de que un carácter puede ser representado de formas diferentes.
Visualicemos con un ejemplo estas diferentes formas de representar un mismo carácter:

        // Representación normal
        char c1 = 'í';
        // Representación UNICODE
        char c2 = '\u00ed';
        // Representación UNICODE en forma canónica
        char[] c3 = {'\u0069', '\u0301'};

¿En qué consiste la representación canónica?

La representación o descomposición canónica consiste simplemente (de forma muy resumida) en la descomposición del carácter en 2 partes:

- Parte 1: Letra base
- Parte 2: Acento

De esta forma, hemos podido representar el carácter i compuesto por la letra i (0×0061) y su acento (0×0301).

Una vez entendido el concepto de descomposición canónica, es hora de ponerlo en práctica para nuestro cometido: limpiar un texto de acentos y caracteres especiales obteniendo de esta manera un texto sólo de caracteres ASCII.

    /**
     * Función que elimina acentos y caracteres especiales de
     * una cadena de texto.
     * @param input
     * @return cadena de texto limpia de acentos y caracteres especiales.
     */
    public static String remove2(String input) {
        // Descomposición canónica
        String normalized = Normalizer.normalize(input, Normalizer.Form.NFD);
        // Nos quedamos únicamente con los caracteres ASCII
        Pattern pattern = Pattern.compile("\\p{ASCII}+");
        return pattern.matcher(normalized).replaceAll("");
    }//remove2

Comprobemos el resultado final de nuestras 2 técnicas:

        System.out.println("1. " + RemoveAccents.remove1("Mañana será un día mejor"));
        System.out.println("2. " + RemoveAccents.remove1("Mañana será un día mejor"));

Tags:

8 respuestas en “Eliminar acentos y caracteres especiales en Java”

  1. La función remove2 no elimina los acentos sino que sólo muestra los acentos que había en el texto. La función remove1 va a la perfección.

    Un saludo y gracias por el código.

  2. Gracias por tu aportación Chema.
    Comprobaré lo que indicas en la función remove2 y actualizaré la entrada con la corrección si procede.
    ¡Un saludo!

  3. Basta con cambiar “\\p{ASCII}+” por “\\P{ASCII}”.

  4. Hola, una consulta.
    Use el codigo de remove1 en una aplicacion RCP echa con eclipse, dentro del eclipse funciona perfecto,pero cuando exporto el producto, me da un error:
    String Index out of range: 34, en la linea:
    output = output.replace(original.charAt(i), ascii.charAt(i));

    Todo lo demas esta exactamente igual.
    Alguna idea? sera un problema de codificacion de caracteres ? y que por algun motivo el largo de la cadena “original” al ejecutable le llega mas corto ?
    Saludos

    • Hola Nic
      En primer lugar gracias por comentar.
      A priori no creo que sea un problema de la codificación, de todas formas, si quieres, puedes intentar registrar un log con la cadena que recibes y la longitud de la misma, así descartamos (o confirmamos) que pueda ser eso.
      ¿Probaste la opción Remove2 con la modificación que indicaba Xel en su comentario?
      ¡Un saludo!

    • Me parece que es por un pequeño error de codificación.

      Habría que cambiar

      for (int i=0; i<original.length(); i++)

      por

      for (int i=0; i<output.length(); i++)

      Un saludo!

  5. Acabo de usar el remove1 para un desarrollo rápido y ha funcionado perfectamente.

    Me la apunto.

    Muchas gracias.

    • Me alegro mucho compañero!
      Gracias por comentar.

Dejar un comentario