Преобразование Java UTF-8 в ASCII с дополнениями
мы принимаем всевозможные национальные символы в строке UTF-8 на входе, и нам нужно преобразовать их в строку ASCII на выходе для некоторого использования устаревшей. (мы не принимаем китайские и японские символы, только европейские языки)
У нас есть небольшая утилита, чтобы избавиться от всех диакритик:
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();
}
Вопрос заключается в том, как заменить все немецкие острый s (ß, Đ, đ) и другие символы, которые проходят через вышеупомянутый метод нормализации, с их дополнениями (в случае ß дополнение, вероятно, будет "ss" и в case od Đ дополнение будет либо "D", либо "Dj" ).
Есть ли простой способ сделать это, без миллионов вызовов .replaceAll()?
Итак, например: Đonardan = Djonardan, Blaß = Blass и т.д.
Мы можем заменить все "проблемные" символы пустым пространством, но хотелось бы избежать этого, чтобы сделать выход как можно более похожим на вход.
Спасибо за ваши ответы,
бозо
Ответы
Ответ 1
Есть ли простой способ сделать это, без миллионов вызовов .replaceAll()?
Если вы просто поддерживаете европейские, латинские языки, должно быть достаточно 100; что определенно выполнимо: захватите Unicode charts для Latin-1 Supplement и Latin Extended-A и начнется вечеринка String.replace
.: -)
Ответ 2
Вы хотите использовать ICU4J. Он включает класс com.ibm.icu.text.Transliterator
, который, по-видимому, может делать то, что вы ищете.
Ответ 3
Я использую что-то вроде этого:
Transliterator transliterator = Transliterator.getInstance("Any-Latin; Upper; Lower; NFD; [:Nonspacing Mark:] Remove; NFC", Transliterator.FORWARD);
Ответ 4
Здесь мой конвертер, который использует 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;
}