2008-11-12 35 views
23

Tenemos un sistema en el que los clientes, principalmente europeos, introducen textos (en UTF-8) que deben distribuirse a diferentes sistemas, la mayoría de ellos aceptando UTF-8, pero ahora también debemos distribuir los textos a un sistema de EE. UU. que solo acepta US-Ascii 7-bitCómo convertir UTF-8 a US-Ascii en Java

Así que ahora necesitaremos traducir todos los caracteres europeos al US-Ascii más cercano. ¿Hay bibliotecas de Java para ayudar con esta tarea?

Ahora mismo hemos empezado a agregar a una tabla de traducción, donde Å (sueco AA) -> A y así sucesivamente y donde no encontramos ninguna coincidencia para un carácter ingresado, lo registraremos y reemplazaremos con un signo de interrogación y tratar de arreglar eso para la próxima versión, pero parece muy ineficiente y alguien más debe haber hecho algo similar antes.

+0

posible duplicado de [conversión en java Encoding] (http://stackoverflow.com/questions/229015/encoding-conversion-in-java) – kamaci

Respuesta

16

El programa uni2ascii está escrito en C, pero probablemente podría convertirlo a Java con poco esfuerzo. Contiene una gran tabla de aproximaciones (implícitamente, en las sentencias switch-case).

Tenga en cuenta que no hay aproximaciones universalmente aceptadas: los alemanes quieren que reemplace Ä por AE, los finlandeses y los suecos prefieren simplemente A. Su ejemplo de Å tampoco es obvio: los suecos probablemente soltarían el anillo y usarían A , pero a los daneses y los noruegos les gustaría más el AA históricamente más correcto.

+2

Excelentes ejemplos sobre las diferencias regionales. –

5

En lugar de crear su propia tabla, podría convertir el texto a la forma de normalización D, donde los caracteres se representan como un carácter base más los signos diacríticos (por ejemplo, "á" será reemplazado por "a" seguido de una combinación de acento agudo). A continuación, puede quitar todo lo que no sea una letra ASCII.

Las tablas aún existen, pero ahora son las del estándar Unicode.

También puede probar NFKD en lugar de NFD, para detectar aún más casos.

Referencias:

+0

Respuesta relacionada: http://stackoverflow.com/questions/225471/how-do-i-replace-accented-latin-characters-in-ruby#226090 – CesarB

1

Esto es típicamente útil en aplicaciones de búsqueda. Consulte la implementación correspondiente de Lucene ISOLatin1AccentFilter. Esto no está realmente diseñado para conectarse a una implementación local aleatoria, pero sí el truco.

-14

Esto es lo que parece funcionar:

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(); 
} 
33

Usted puede hacer esto con la siguiente (a partir del ejemplo NFD en this Core Java Technology Tech Tip):

public static String decompose(String s) { 
    return java.text.Normalizer.normalize(s, java.text.Normalizer.Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+",""); 
} 
+2

NB: En scala esto sería: def decompose (s: String): String = java.text.Normalizer.normalize (s, java.text.Normalizer.Form.NFD) .replaceAll ("\\ p {InCombiningDiacriticalMarks} +", "") –

+0

El enlace está roto. –

+0

Gracias Michaël; He arreglado el enlace (ahora apunta a Wayback Machine de Internet Archive ya que el contenido ya no está disponible). –

-3

esto es lo que yo uso:

<?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; 
} 
?> 
-1

nuevo Cadena ("½".getBytes ("US-ASCII"))

4

En respuesta a la answer given by Joe Liversedge, la Lucene referencia ISOLatin1AccentFilterya no existe:

Ha sido reemplazado por org.apache.lucene.analysis.ASCIIFoldingFilter:

Esta clase conversos Caracteres Unicode alfabéticos, numéricos y simbólicos que no están en los primeros 127 caracteres ASCII (el bloque Unicode "Latin básico") en sus equivalentes ASCII, si existe alguno. Los caracteres de los siguientes bloques Unicode se convierten; sin embargo, solo aquellos caracteres con alternativas ASCII razonables se convierten.

FYI -