Как конвертировать UTF-8 в US-Ascii в Java
У нас есть система, в которой клиенты, в основном европейские, вводят тексты (в UTF-8), которые должны быть распределены по разным системам, большинство из которых принимают UTF-8, но теперь мы также должны распространять тексты в американской системе, которая принимает только США. -Асия 7-битная
Так что теперь нам нужно перевести все европейские символы в ближайшую US-Ascii. Есть ли библиотеки Java, чтобы помочь с этой задачей?
Прямо сейчас мы только начали добавлять в таблицу перевода, где Å (шведский AA)->A и т. Д., И где мы не нашли соответствия для введенного символа, мы запишем его и заменим знаком вопроса и попытаться исправить это в следующем выпуске, но это кажется очень неэффективным, и кто-то еще должен был что-то сделать раньше.
9 ответов
Программа uni2ascii написана на C, но вы, вероятно, сможете конвертировать ее в Java без особых усилий. Он содержит большую таблицу приближений (неявно в операторах switch-case).
Имейте в виду, что нет общепринятых приближений: немцы хотят, чтобы вы заменили Ä на AE, финны и шведы предпочитают только A. Ваш пример Å также не очевиден: шведы, вероятно, просто бросят кольцо и будут использовать A, но датчане и Норвежцам может понравиться исторически более правильный АА.
Это можно сделать с помощью следующего (из примера NFD в этом техническом совете по технологии Java):
public static String decompose(String s) {
return java.text.Normalizer.normalize(s, java.text.Normalizer.Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+","");
}
Вместо того, чтобы создавать свою собственную таблицу, вы могли бы вместо этого преобразовать текст в форму нормализации D, где символы представлены как базовый символ плюс диакритические знаки (например, "á" будет заменено на "a", за которым следует сочетание острого акцента). Затем вы можете удалить все, что не является буквой ASCII.
Таблицы все еще существуют, но теперь они из стандарта Unicode.
Вы также можете попробовать NFKD вместо NFD, чтобы поймать еще больше случаев.
Рекомендации:
В ответ на ответ Джо Ливерседжа, ссылка на Lucene ISOLatin1AccentFilter больше не существует:
Он был заменен на org.apache.lucene.analysis.ASCIIFoldingFilter:
Этот класс преобразует буквенные, числовые и символьные символы Unicode, которые не входят в первые 127 символов ASCII (блок Unicode "Basic Latin"), в их эквиваленты ASCII, если таковые существуют. Символы из следующих блоков Unicode конвертируются; однако, только те символы с разумными альтернативами ASCII конвертируются.
К вашему сведению -
Это обычно полезно в поисковых приложениях. См. Соответствующую реализацию Lucene ISOLatin1AccentFilter. Это на самом деле не предназначено для подключения к случайной локальной реализации, но делает свое дело.
Для этого есть несколько встроенных функций. Основной участвующий класс CharsetEncoder
, которая является частью nio
пакет. Более простой способ String.getBytes(Charset)
которые могут быть отправлены ByteArrayOutputStream
,
Это то, что я использую:
<?php
function remove_accent($str) {
# http://www.php.net/manual/en/function.preg-replace.php#96586
$a = array('À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'ß', 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', 'Ā', 'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ', 'ĉ', 'Ċ', 'ċ', 'Č', 'č', 'Ď', 'ď', 'Đ', 'đ', 'Ē', 'ē', 'Ĕ', 'ĕ', 'Ė', 'ė', 'Ę', 'ę', 'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ', 'ğ', 'Ġ', 'ġ', 'Ģ', 'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī', 'Ĭ', 'ĭ', 'Į', 'į', 'İ', 'ı', 'IJ', 'ij', 'Ĵ', 'ĵ', 'Ķ', 'ķ', 'Ĺ', 'ĺ', 'Ļ', 'ļ', 'Ľ', 'ľ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'Ń', 'ń', 'Ņ', 'ņ', 'Ň', 'ň', 'ʼn', 'Ō', 'ō', 'Ŏ', 'ŏ', 'Ő', 'ő', 'Œ', 'œ', 'Ŕ', 'ŕ', 'Ŗ', 'ŗ', 'Ř', 'ř', 'Ś', 'ś', 'Ŝ', 'ŝ', 'Ş', 'ş', 'Š', 'š', 'Ţ', 'ţ', 'Ť', 'ť', 'Ŧ', 'ŧ', 'Ũ', 'ũ', 'Ū', 'ū', 'Ŭ', 'ŭ', 'Ů', 'ů', 'Ű', 'ű', 'Ų', 'ų', 'Ŵ', 'ŵ', 'Ŷ', 'ŷ', 'Ÿ', 'Ź', 'ź', 'Ż', 'ż', 'Ž', 'ž', 'ſ', 'ƒ', 'Ơ', 'ơ', 'Ư', 'ư', 'Ǎ', 'ǎ', 'Ǐ', 'ǐ', 'Ǒ', 'ǒ', 'Ǔ', 'ǔ', 'Ǖ', 'ǖ', 'Ǘ', 'ǘ', 'Ǚ', 'ǚ', 'Ǜ', 'ǜ', 'Ǻ', 'ǻ', 'Ǽ', 'ǽ', 'Ǿ', 'ǿ');
$b = array('A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 's', 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'y', 'A', 'a', 'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 'D', 'd', 'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'G', 'g', 'G', 'g', 'G', 'g', 'G', 'g', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'IJ', 'ij', 'J', 'j', 'K', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'l', 'l', 'N', 'n', 'N', 'n', 'N', 'n', 'n', 'O', 'o', 'O', 'o', 'O', 'o', 'OE', 'oe', 'R', 'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'T', 't', 'T', 't', 'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'W', 'w', 'Y', 'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's', 'f', 'O', 'o', 'U', 'u', 'A', 'a', 'I', 'i', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'A', 'a', 'AE', 'ae', 'O', 'o');
return str_replace($a, $b, $str);
}
function SEOify($i){
# http://php.ca/manual/en/function.preg-replace.php#90316
$o = $i;
$o = html_entity_decode($o,ENT_COMPAT,'UTF-8');
$o = remove_accent(trim($o));
$patterns = array( "([\40])" , "([^a-zA-Z0-9_-])", "(-{2,})" );
$replacers = array("-", "", "-");
$o = preg_replace($patterns, $replacers, $o);
return $o;
}
?>
Вот что похоже на работу:
private synchronized static String utftoasci(String s){
final StringBuffer sb = new StringBuffer( s.length() * 2 );
final StringCharacterIterator iterator = new StringCharacterIterator( s );
char ch = iterator.current();
while( ch != StringCharacterIterator.DONE ){
if(Character.getNumericValue(ch)>0){
sb.append( ch );
}else{
boolean f=false;
if(Character.toString(ch).equals("Ê")){sb.append("E");f=true;}
if(Character.toString(ch).equals("È")){sb.append("E");f=true;}
if(Character.toString(ch).equals("ë")){sb.append("e");f=true;}
if(Character.toString(ch).equals("é")){sb.append("e");f=true;}
if(Character.toString(ch).equals("è")){sb.append("e");f=true;}
if(Character.toString(ch).equals("è")){sb.append("e");f=true;}
if(Character.toString(ch).equals("Â")){sb.append("A");f=true;}
if(Character.toString(ch).equals("ä")){sb.append("a");f=true;}
if(Character.toString(ch).equals("ß")){sb.append("ss");f=true;}
if(Character.toString(ch).equals("Ç")){sb.append("C");f=true;}
if(Character.toString(ch).equals("Ö")){sb.append("O");f=true;}
if(Character.toString(ch).equals("º")){sb.append("");f=true;}
if(Character.toString(ch).equals("Ó")){sb.append("O");f=true;}
if(Character.toString(ch).equals("ª")){sb.append("");f=true;}
if(Character.toString(ch).equals("º")){sb.append("");f=true;}
if(Character.toString(ch).equals("Ñ")){sb.append("N");f=true;}
if(Character.toString(ch).equals("É")){sb.append("E");f=true;}
if(Character.toString(ch).equals("Ä")){sb.append("A");f=true;}
if(Character.toString(ch).equals("Å")){sb.append("A");f=true;}
if(Character.toString(ch).equals("ä")){sb.append("a");f=true;}
if(Character.toString(ch).equals("Ü")){sb.append("U");f=true;}
if(Character.toString(ch).equals("ö")){sb.append("o");f=true;}
if(Character.toString(ch).equals("ü")){sb.append("u");f=true;}
if(Character.toString(ch).equals("á")){sb.append("a");f=true;}
if(Character.toString(ch).equals("Ó")){sb.append("O");f=true;}
if(Character.toString(ch).equals("É")){sb.append("E");f=true;}
if(!f){
sb.append("?");
}
}
ch = iterator.next();
}
return sb.toString();
}