8
votes

Comment supprimer des caractères Unicode non valides des chaînes en Java

J'utilise le Parser de dépendance de réseau Neural Corenlp pour analyser certains Contenu des médias sociaux. Malheureusement, le fichier contient des caractères qui sont, selon FileFormat.info , non valides caractères unicode ou caractères de remplacement unicode. Celles-ci sont par exemple U + D83D ou u + fffd . Si ces caractères sont dans le fichier, CorenLP répond avec des messages d'erreur comme celui-ci: xxx

basé sur Cette réponse, j'ai essayé document.replaceall (" \\ p {c} "," "); Pour simplement supprimer ces personnages. Document Voici le document comme une chaîne. Mais cela n'a pas aidé.

Comment puis-je supprimer ces personnages de la chaîne avant de la transmettre à corenlp?

Mise à jour (16 nov.):

Par souci de complétude, je ne devrais mentionner que j'ai posé cette question uniquement afin d'éviter l'énorme quantité de messages d'erreur en prétraitant le fichier. Corenlp ignore simplement les caractères qu'il ne peut pas gérer, donc ce n'est pas le problème.


2 commentaires

La méthode de remplacement crée une nouvelle chaîne ; Il ne modifie pas document . Avez-vous fait document = document.replaceall (...) (ou quelque chose d'autre pour capturer la valeur de retour)?


Je l'ai utilisé dans l'instanciation de la catégorie DocumentProcessor de cette ligne: DocumentPreprocessor Tokenizer = Nouveau DocumentPrarocessor (Nouveau StringReader (Document.ReplaceAll ("\\ p {c}", "")) ); .


4 Réponses :


1
votes

Tout comme vous avez une chaîne comme

chaîne xml = "...."; xml = xml.replaceall ("[^ \ u0009 \ u000a \ u000d \ u0020- \ ud7ff \ ue000- \ ufffd]", "");

Cela résoudra votre problème


3 commentaires

Il est indiqué que String Literal n'est pas correctement fermé par une double citation .


Tous les \ u ont besoin de double évasion -> \\ u


HM, OK, ça a fait l'affaire. Les erreurs u + d83d semblent disparaître, peut-être aussi d'autres (j'ai un énorme corpus, alors je ne suis pas sûr). Ce que je reçois toujours est u + fffd , u + fe0f , u + 203c et u + 3010 . Au moins, je ne vois rien d'autre dans la ruée. Comment puis-je me débarrasser de ceux-ci? Une autre chose, pourriez-vous spécifier ce qui est supprimé exactement? Je veux être sûr que rien je ne veux pas être supprimé est supprimé.



3
votes

Supprimer des caractères indésirables spécifiques avec: xxx

Si vous avez trouvé d'autres caractères non désirés, ajoutez simplement avec le même schéma à la liste.

>:

Les caractères Unicode sont écartés par le moteur de regex dans 7 groupes macro-groupes (et plusieurs sous-groupes) identifiés par une lettre (groupe macro-groupe) ou deux lettres (sous-groupe). < / p>

Baser mes arguments sur vos exemples et les classes Unicode indiquées dans la toujours bonne ressource Site d'expressions je pense que vous pouvez essayer une approche unique bonne-passe telle que celle-ci: xxx

Cette regex supprimer tout ce que n'est pas:

  • \ p {l} : une lettre dans n'importe quelle langue
  • \ p {n} : un numéro
  • \ p {z} : n'importe quel type de type de blancheur ou séparateur invisible
  • \ p {sm} \ p {sc} \ p {sk} : mathématiques, monnaie ou marques génériques comme un seul char
  • \ p {mc} * : un personnage destiné à être combiné avec un autre caractère qui prend un espace supplémentaire (signes voyelles dans de nombreuses langues orientales).
  • \ p {pi} \ p {pf} \ p {pc} * : Devis d'ouverture, citation de fermeture, connecteurs de mots (c'est-à-dire un trait de soulignement)

    * : Je pense que ces groupes peuvent être éligibles pour être éliminés également à des fins de corenpl.

    De cette façon, vous n'avez besoin que d'un seul filtre de regex et vous pouvez gérer des groupes de caractères (avec le même objectif) au lieu de cas simples.


3 commentaires

Merci pour la mise à jour. Je pense que cela pourrait être trop, cependant. Par exemple, un problème était u + 3010 ( FileFormat.info/info/unicode/char/3010/index.htm ), qui appartient au groupe PS (n'importe quel type de support d'ouverture). Mais ne serait-ce pas aussi (, [ou {être retiré, inutilement dans mon cas? Avant de commencer à supprimer des trucs, je ne veux pas, je préfère vivre avec les messages d'erreur et laisser Corenlp faire le travail lui-même.


Testez s'il existe des différences dans la sortie fournie par Corenpl en utilisant le filtre (peut-être que c'est le cas, peut-être pas). Être une liste blanche Vous pouvez toujours simplement ajouter les caractères que vous souhaitez enregistrer dans la liste, c'est-à-dire "[^ \\ p {l} .. \\ (\\) \\ [\\] \\ {\\}) ".


Oui tu as raison. Probablement la meilleure solution à mon problème. Merci!



7
votes

D'une manière, les deux réponses fournies par Mukesh Kumar et Gsusrecovery aident, mais pas complètement correct.

DocumentPreprocessor tokenizer = new DocumentPreprocessor(new StringReader(document));
TokenizerFactory<? extends HasWord> factory=null;
factory=PTBTokenizer.factory();
factory.setOptions("untokenizable=noneDelete");
tokenizer.setTokenizerFactory(factory);

for (List<HasWord> sentence : tokenizer) {
    // do something with the sentence
}


1 commentaires

Bon travail, j'ai mis à jour ma réponse pour optimiser le processus en utilisant une approche unique "non dans l'une des groupes UNICODE-Groupe autorisée". Essayez-le et lisez la documentation associée. En attente d'une réponse officielle pour la raffinement éventuellement, je pense être la meilleure approche.



0
votes

a observé l'impact négatif dans d'autres endroits où nous faisons la lettre de remplacement. Donc, je propose de remplacer les caractères s'il s'agit de caractères non BPM comme ci-dessous

private String removeNonBMPCharacters(final String input) {
    StringBuilder strBuilder = new StringBuilder();
    input.codePoints().forEach((i) -> {
        if (Character.isSupplementaryCodePoint(i)) {
            strBuilder.append("?");
        } else {
            strBuilder.append(Character.toChars(i));
        }
    });
    return strBuilder.toString();
}


0 commentaires