У нас есть система, в которой клиенты, в основном европейцы, вводят тексты (в UTF-8), которые должны быть распределены по разным системам, большинство из которых принимают UTF-8, но теперь мы также должны распространять тексты в систему США, которая принимает только США. -Ascii 7-битный
Итак, теперь нам нужно перевести все европейские символы в ближайший US-Ascii. Есть ли какие-нибудь библиотеки Java, которые помогут с этой задачей?
Прямо сейчас мы только начали добавлять в таблицу перевода, где Å (шведский AA) -> A и так далее, и где мы не находим совпадения для введенного символа, мы зарегистрируем его и заменим знаком вопроса и попытайтесь исправить это в следующем выпуске, но это кажется очень неэффективным, и кто-то другой, должно быть, делал что-то подобное раньше.
Вы нашли решение? Я имею в виду, что это было 11 лет назад, но может быть?
Мы создали нашу собственную таблицу сопоставления, далеко не полную, но удовлетворившую наши потребности.




Для этого есть несколько встроенных функций. Основной задействованный класс - это CharsetEncoder, который является частью пакета nio. Более простой способ - это String.getBytes(Charset), который может быть отправлен на ByteArrayOutputStream.
Это не касается нормализации от «é» до «e».
Программа uni2ascii написана на C, но вы, вероятно, сможете преобразовать ее в Java без особых усилий. Он содержит большую таблицу приближений (неявно, в операторах switch-case).
Имейте в виду, что не существует общепринятых приближений: немцы хотят, чтобы вы заменили Ä на AE, финны и шведы предпочитают только A. Ваш пример Å также неочевиден: шведы, вероятно, просто отказались бы от кольца и использовали бы A, но датчане и Норвежцам могло бы больше понравиться исторически более правильное АА.
Отличные примеры региональных различий.
Вместо того, чтобы создавать свою собственную таблицу, вы могли бы вместо этого преобразовать текст в форму нормализации D, где символы представлены как базовый символ плюс диакритические знаки (например, «á» будет заменено на «a» с последующим комбинированным острым ударением. ). Затем вы можете удалить все, что не является буквой ASCII.
Таблицы все еще существуют, но теперь они соответствуют стандарту Unicode.
Вы также можете попробовать NFKD вместо NFD, чтобы поймать еще больше случаев.
Использованная литература:
Связанный ответ: stackoverflow.com/questions/225471/…
Обычно это полезно в поисковых приложениях. См. Соответствующую реализацию Lucene ISOLatin1AccentFilter. На самом деле это не предназначено для включения в случайную локальную реализацию, но помогает.
Вот что вроде работает:
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();
}
Вы можете сделать это следующим образом (из примера NFD в этот технический совет по основным технологиям Java):
public static String decompose(String s) {
return java.text.Normalizer.normalize(s, java.text.Normalizer.Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+","");
}
NB: В scala это будет: def decopose (s: String): String = java.text.Normalizer.normalize (s, java.text.Normalizer.Form.NFD) .replaceAll ("\\ p {InCombiningDi acriticalMarks} + "," ")
вот что я использую:
<?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;
}
?>
новая строка ("½" .getBytes ("US-ASCII"))
В ответ на ответ, данный Джо Ливерседжем указанный Lucene ISOLatin1AccentFilterбольше не существует:
Он был заменен на org.apache.lucene.analysis.ASCIIFoldingFilter:
This class converts alphabetic, numeric, and symbolic Unicode characters which are not in the first 127 ASCII characters (the "Basic Latin" Unicode block) into their ASCII equivalents, if one exists. Characters from the following Unicode blocks are converted; however, only those characters with reasonable ASCII alternatives are converted.
К вашему сведению -
возможный дубликат Преобразование кодировки в java