eliminar caracteres de un rango Unicode específico de una cadena

Tengo un progtwig que analiza los tweets en tiempo real de la API de Twitter. Antes de almacenarlos, los estoy codificando como utf8. Ciertos personajes terminan apareciendo en la cadena como?, ??, o ??? en lugar de sus respectivos códigos Unicode y causar problemas. Tras una investigación más profunda, descubrí que los personajes problemáticos son del bloque “emoticon” , U + 1F600 – U + 1F64F, y el bloque “Símbolos y pictogtwigs misceláneos ” , U + 1F300 – U + 1F5FF. Traté de eliminarlo, pero no tuve éxito ya que el emparejador terminó reemplazando casi todos los caracteres de la cadena, no solo mi rango Unicode deseado.

String utf8tweet = ""; try { byte[] utf8Bytes = status.getText().getBytes("UTF-8"); utf8tweet = new String(utf8Bytes, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } Pattern unicodeOutliers = Pattern.compile("[\\u1f300-\\u1f64f]", Pattern.UNICODE_CASE | Pattern.CANON_EQ | Pattern.CASE_INSENSITIVE); Matcher unicodeOutlierMatcher = unicodeOutliers.matcher(utf8tweet); utf8tweet = unicodeOutlierMatcher.replaceAll(" "); 

¿Qué puedo hacer para eliminar estos personajes?

En el patrón de expresiones regulares, agregue el operador de negación ^ . Para filtrar caracteres imprimibles, puede usar la siguiente expresión [^\\x00-\\x7F] y obtendrá el resultado deseado.

 import java.io.UnsupportedEncodingException; import java.util.regex.Matcher; import java.util.regex.Pattern; public class UTF8 { public static void main(String[] args) { String utf8tweet = ""; try { byte[] utf8Bytes = "#Hello twitter  How are you?".getBytes("UTF-8"); utf8tweet = new String(utf8Bytes, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } Pattern unicodeOutliers = Pattern.compile("[^\\x00-\\x7F]", Pattern.UNICODE_CASE | Pattern.CANON_EQ | Pattern.CASE_INSENSITIVE); Matcher unicodeOutlierMatcher = unicodeOutliers.matcher(utf8tweet); System.out.println("Before: " + utf8tweet); utf8tweet = unicodeOutlierMatcher.replaceAll(" "); System.out.println("After: " + utf8tweet); } } 

Resultados en el siguiente resultado:

 Before: #Hello twitter  How are you? After: #Hello twitter How are you? 

EDITAR

Para seguir explicando, también podría seguir expresando el rango con el formulario \u de la siguiente manera [^\\u0000-\\u007F] , que coincidirá con todos los caracteres que no sean los primeros 128 caracteres UNICODE (los mismos que antes) ) Si desea ampliar el rango para admitir caracteres adicionales, puede hacerlo usando la lista de caracteres UNICODE aquí .

Por ejemplo, si desea incluir vocales con acento (usadas en español), debe extender el rango a \u00FF , por lo que tiene [^\\u0000-\\u00FF] o [^\\x00-\\xFF] :

 Before: #Hello twitter  How are you? á é í ó ú After: #Hello twitter How are you? á é í ó ú 

En primer lugar, el bloque Unicode en cuestión se especifica en Java (siguiendo estrictamente el estándar) como Character.UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS . En una expresión regular:

 s = s.replaceAll("\\p{So}+", ""); 

Intenté esto. Los rangos Unicode son de rangos emoji

  class EmojiEraser{ private static final String EMOJI_RANGE_REGEX = "[\uD83C\uDF00-\uD83D\uDDFF]|[\uD83D\uDE00-\uD83D\uDE4F]|[\uD83D\uDE80-\uD83D\uDEFF]|[\u2600-\u26FF]|[\u2700-\u27BF]"; private static final Pattern PATTERN = Pattern.compile(EMOJI_RANGE_REGEX); /** * Finds and removes emojies from @param input * * @param input the input string potentially containing emojis (comes as unicode stringfied) * @return input string with emojis replaced */ public String eraseEmojis(String input) { if (Strings.isNullOrEmpty(input)) { return input; } Matcher matcher = PATTERN.matcher(input); StringBuffer sb = new StringBuffer(); while (matcher.find()) { matcher.appendReplacement(sb, ""); } matcher.appendTail(sb); return sb.toString(); } } 

Asumiendo status.getText() devuelve un java.lang.String

 byte[] utf8Bytes = status.getText().getBytes("UTF-8"); utf8tweet = new String(utf8Bytes, "UTF-8"); 

La operación de transencoding anterior produce los mismos resultados que:

 utf8tweet = status.getText(); 

Las cadenas de Java son implícitamente UTF-16. UTF-16 y UTF-8 comparten el mismo conjunto de caracteres (Unicode), por lo que se transforman de uno a otro y los resultados se obtienen en los datos originales.

Las expresiones regulares de Java soportan el rango suplementario usando pares sustitutos . Puede combinarlos como se describe en las respuestas a esta pregunta .

Como señala Eee en su comentario, lo más probable es que tenga un problema con la fuente. Si se puede mostrar un grafema generalmente depende de las fonts disponibles en el sistema del usuario, la fuente elegida y la forma de sustitución de fonts que admite la tecnología de representación.