2010-03-30 13 views
10

estamos aceptando todo tipo de caracteres nacionales en cadena UTF-8 en la entrada, y tenemos que convertirlos en cadenas ASCII en la salida para algún uso heredado. (No se aceptan caracteres chinos y japoneses, sólo los idiomas europeos)Conversión de Java UTF-8 a ASCII con suplementos

Hemos una pequeña utilidad para deshacerse de todos los signos diacríticos:

public static final String toBaseCharacters(final String sText) { 
    if (sText == null || sText.length() == 0) 
     return sText; 

    final char[] chars = sText.toCharArray(); 
    final int iSize = chars.length; 
    final StringBuilder sb = new StringBuilder(iSize); 

    for (int i = 0; i < iSize; i++) { 
     String sLetter = new String(new char[] { chars[i] }); 
     sLetter = Normalizer.normalize(sLetter, Normalizer.Form.NFC); 

     try { 
      byte[] bLetter = sLetter.getBytes("UTF-8"); 
      sb.append((char) bLetter[0]); 
     } catch (UnsupportedEncodingException e) { 
     } 
    } 
    return sb.toString(); 
} 

La cuestión es cómo reemplazar todos los alemanes afilados s (ß, Đ, đ) y otros personajes que obtienen el método de normalización anterior, con sus suplementos (en el caso de ß, el suplemento sería probablemente "ss" y en caso de que el Đ suplemento sea "D" o "Dj")

¿Hay alguna manera simple de hacerlo, sin millones de llamadas a .replaceAll()?

Así, por ejemplo: Đonardan = Djonardan, Blaß = Blass y así sucesivamente.

Podemos reemplazar todos los caracteres "problemáticos" con espacio vacío, pero nos gustaría evitar que la salida sea lo más similar posible a la entrada.

Gracias por sus respuestas,

Bozo

+5

Tenga en cuenta que no hay una correspondencia unívoca: En alemán, se sustituye "ö" por "oe", mientras que en sueco, "ö" se reemplaza por "o". – Heinzi

+0

Tendrá que tener esta función para tomar un parámetro de idioma y posiblemente tener un idioma predeterminado. O dedique algo de tiempo a tratar de encontrar una manera de decidir de qué lenguaje procedería la cuerda, pero eso se frenará si la cuerda no es lo suficientemente larga. De cualquier manera, parece que necesitará una tabla de búsqueda de algún tipo. Deje que su aplicación revise toda la cadena, verificando cada carácter y descubriendo con qué se debe intercambiar. – thecoshman

+0

Otra opción podría ser reemplazar "ö" con "o:" como una especie de "diacrítico del pobre". –

Respuesta

0

¿Hay alguna forma sencilla de hacerlo, sin millones de .ReplaceAll() llama?

Si solo admite idiomas europeos basados ​​en el latín, aproximadamente 100 deberían ser suficientes; eso es definitivamente factible: tome el Unicode charts para Latin-1 Supplement y Latin Extended-A y obtenga la fiesta String.replace comenzada. :-)

+1

No puedo creer que nadie haya hecho esto, haya hecho algunos mapas y haya dicho que aquí hay uno para las personas que lo prefieran de esta manera, amplíelo si desea algunas modificaciones según sus necesidades. – bozo

2

Quiere usar ICU4J. Incluye la clase com.ibm.icu.text.Transliterator, que aparentemente puede hacer lo que estás buscando.

+1

Excepto que los transliteradores ICU4J que he probado son extremadamente inexactos (latín, cirílico y hangul), ¿cuál transliterador exacto crees que cumpliría con la solicitud original? No puedo encontrar nada aparentemente adecuado. – jarnbjo

+0

He intentado con ICU4J y fue tan complicado que ni siquiera pude ejecutarlo. – bozo

1

estoy usando algo como esto:

Transliterator transliterator = Transliterator.getInstance("Any-Latin; Upper; Lower; NFD; [:Nonspacing Mark:] Remove; NFC", Transliterator.FORWARD); 
1

Aquí es mi convertidor que utiliza Lucene ...

private final KeywordTokenizer keywordTokenizer = new KeywordTokenizer(new StringReader("")); 
private final ASCIIFoldingFilter asciiFoldingFilter = new ASCIIFoldingFilter(keywordTokenizer); 
private final TermAttribute termAttribute = (TermAttribute) asciiFoldingFilter.getAttribute(TermAttribute.class); 

public String process(String line) 
{ 
    if (line != null) 
    { 
     try 
     { 
      keywordTokenizer.reset(new StringReader(line)); 
      if (asciiFoldingFilter.incrementToken()) 
      { 
       return termAttribute.term(); 
      } 
     } 
     catch (IOException e) 
     { 
      logger.warn("Failed to parse: " + line, e); 
     } 
    } 
    return null; 
} 
Cuestiones relacionadas