2010-03-30 19 views
10

stiamo accettando tutti i tipi di caratteri nazionali nella stringa UTF-8 sull'input e abbiamo bisogno di convertirli in stringa ASCII sull'output per un uso legacy. (Non si accettano caratteri cinesi e giapponesi, solo le lingue europee)Conversione da UTF-8 a ASCII Java con supplementi

Abbiamo una piccola utility per sbarazzarsi di tutti i segni diacritici:

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 domanda è come sostituire tutti i s taglienti tedesco (ß, Đ, đ) e altri personaggi che superano il suddetto metodo di normalizzazione, con i loro supplementi (in caso di ß, il supplemento sarebbe probabilmente "ss" e nel caso in cui Đ supplemento sarebbe "D" o "Dj").

C'è un modo semplice per farlo, senza milioni di chiamate .replaceAll()?

Ad esempio: Đonardan = Djonardan, Blaß = Blass e così via.

Possiamo sostituire tutti i caratteri "problematici" con spazio vuoto, ma vorrei evitare questo per rendere l'output il più simile possibile all'input.

Grazie per le vostre risposte,

Bozo

+5

Si noti che non v'è alcuna mappatura unica: In tedesco, "ö" è sostituito con "oe", mentre in svedese "ö" è sostituito da "o". – Heinzi

+0

È necessario che questa funzione contenga un parametro di lingua e possibilmente abbia una lingua predefinita. O passare un po 'di tempo a cercare un modo per decidere da quale lingua sarebbe venuta la stringa, ma ciò frenerebbe se la stringa non fosse abbastanza lunga. in entrambi i casi, sembra che avrete bisogno di una tabella di ricerca di alcuni tipi. Lascia che l'app passi attraverso l'intera stringa, controllando ogni personaggio e trovando ciò che dovrebbe essere scambiato. – thecoshman

+0

Un'altra opzione potrebbe sostituire "ö" con "o:" come una sorta di "diacritico di un povero uomo". –

risposta

0

C'è qualche modo semplice per farlo, senza milioni di .ReplaceAll() chiama?

Se si supportano solo lingue europee, in lingua latina, circa 100 dovrebbero essere sufficienti; questo è sicuramente fattibile: prendi lo Unicode charts per Latin-1 Supplement e Latin Extended-A e inizia la festa String.replace. :-)

+1

Non posso credere che nessuno lo abbia fatto, abbia creato alcune mappe e detto, eccone uno per le persone che preferiscono questo o quel modo, estendilo se desideri qualche modifica per le tue esigenze. – bozo

2

Si desidera utilizzare ICU4J. Include la classe com.ibm.icu.text.Transliterator, che a quanto pare può fare ciò che stai cercando.

+1

Tranne che i traslitteratori ICU4J che ho provato sono estremamente imprecisi (latino, cirillico e hangul), quale esatto traslitteratore pensate possa soddisfare la richiesta originale? Non sono in grado di trovare nulla apparentemente adatto. – jarnbjo

+0

Ho provato ICU4J ed è stato così complicato da non riuscire nemmeno a eseguirlo. – bozo

1

sto usando qualcosa di simile:

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

Ecco il mio convertitore che usa 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; 
}