Saltar al contenido

Cómo eliminar caracteres unicode no válidos de cadenas en java

Luego de de nuestra extensa selección de información hemos podido resolver esta contrariedad que presentan ciertos los usuarios. Te ofrecemos la respuesta y esperamos serte de mucha ayuda.

En cierto modo, ambas respuestas proporcionadas por Mukesh Kumar y GsusRecovery ayudan, pero no son completamente correctas.

document.replaceAll("[^\u0009\u000a\u000d\u0020-\uD7FF\uE000-\uFFFD]", "");

parece reemplazar todos los caracteres no válidos. Pero CoreNLP parece no admitir aún más. Los descubrí manualmente ejecutando el analizador en todo mi corpus, lo que llevó a esto:

document.replaceAll("[\uD83D\uFFFD\uFE0F\u203C\u3010\u3011\u300A\u166D\u200C\u202A\u202C\u2049\u20E3\u300B\u300C\u3030\u065F\u0099\u0F3A\u0F3B\uF610\uFFFC]", "");

Así que ahora mismo estoy ejecutando dos replaceAll() comandos antes de entregar el documento al analizador. El fragmento de código completo es

// remove invalid unicode characters
String tmpDoc1 = document.replaceAll("[^\u0009\u000a\u000d\u0020-\uD7FF\uE000-\uFFFD]", "");
// remove other unicode characters coreNLP can't handle
String tmpDoc2 = tmpDoc1.replaceAll("[\uD83D\uFFFD\uFE0F\u203C\u3010\u3011\u300A\u166D\u200C\u202A\u202C\u2049\u20E3\u300B\u300C\u3030\u065F\u0099\u0F3A\u0F3B\uF610\uFFFC]", "");
DocumentPreprocessor tokenizer = new DocumentPreprocessor(new StringReader(tmpDoc2));
for (List sentence : tokenizer) 
    List tagged = tagger.tagSentence(sentence);
    GrammaticalStructure gs = parser.predict(tagged);
    System.err.println(gs);

Sin embargo, esta no es necesariamente una lista completa de caracteres no admitidos, razón por la cual abrí un problema en GitHub.

Tenga en cuenta que CoreNLP elimina automáticamente esos caracteres no compatibles. La única razón por la que quiero preprocesar mi corpus es para evitar todos esos mensajes de error.

ACTUALIZACIÓN 27 de noviembre

Christopher Manning acaba de responder el problema de GitHub que abrí. Hay varias formas de manejar esos personajes usando la clase edu.stanford.nlp.process.TokenizerFactory;. Tome este ejemplo de código para tokenizar un documento:

DocumentPreprocessor tokenizer = new DocumentPreprocessor(new StringReader(document));
TokenizerFactory factory=null;
factory=PTBTokenizer.factory();
factory.setOptions("untokenizable=noneDelete");
tokenizer.setTokenizerFactory(factory);

for (List sentence : tokenizer) 
    // do something with the sentence

Puedes reemplazar noneDeleteen línea 4 con otras opciones. Estoy citando a Manning:

“(…) el conjunto completo de seis opciones que combinan si registrar una advertencia para ninguna, la primera o todas, y si eliminarlas o incluirlas como tokens de un solo carácter en la salida: noneDelete, firstDelete, allDelete, noneKeep, firstKeep, allKeep “.

Eso significa que, para mantener los caracteres sin recibir todos esos mensajes de error, la mejor manera es usar la opción noneKeep. De esta forma es mucho más elegante que cualquier intento de eliminar esos caracteres.

Elimine caracteres no deseados específicos con:

document.replaceAll("[\uD83D\uFFFD\uFE0F\u203C\u3010]", "");

Si encontró otros caracteres no deseados, simplemente agréguelos con el mismo esquema a la lista.

ACTUALIZAR:

El motor de expresiones regulares divide los caracteres Unicode en 7 macro-grupos (y varios subgrupos) identificados por una letra (macro-grupo) o dos letras (subgrupo).

Basando mis argumentos en sus ejemplos y las clases Unicode indicadas en el sitio de expresiones regulares de recursos siempre buenos, creo que puede probar un único solo-buen-pase enfoque como este:

document.replaceAll("[^\pL\pN\pZ\pSm\pSc\pSk\pPi\pPf\pPc\pMc]","")

Esta expresión regular elimina todo lo que no sea:

  • pL: una carta en cualquier idioma
  • pN: un número
  • pZ: cualquier tipo de espacio en blanco o separador invisible
  • pSmpScpSk: Matemáticas, Moneda o marcas genéricas como un solo carácter
  • pMc*: un carácter destinado a combinarse con otro carácter que ocupa más espacio (signos de vocales en muchos idiomas orientales).
  • pPipPfpPc*: Cita de apertura, cita de cierre, conectores de palabras (es decir, guión bajo)

*: Creo que estos grupos también pueden ser elegibles para ser eliminados a los efectos de CoreNPL.

De esta manera, solo necesita un filtro de expresiones regulares y puede manejar grupos de caracteres (con el mismo propósito) en lugar de casos individuales.

Si crees que ha resultado útil este artículo, te agradeceríamos que lo compartas con más seniors de este modo contrubuyes a extender esta información.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags :

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *