如何从java中的字符串中删除无效的unicode字符

Yan*_*off 7 java regex unicode parsing stanford-nlp

我正在使用CoreNLP神经网络依赖性解析器来解析一些社交媒体内容.不幸的是,该文件包含的字符根据fileformat.info,不是有效的unicode字符或unicode替换字符.这些是例如U + D83DU + FFFD.如果这些字符在文件中,coreNLP会回复错误消息,如下所示:

Nov 15, 2015 5:15:38 PM edu.stanford.nlp.process.PTBLexer next
WARNING: Untokenizable: ? (U+D83D, decimal: 55357)
Run Code Online (Sandbox Code Playgroud)

根据这个答案,我试图document.replaceAll("\\p{C}", "");删除这些字符.document这里只是一个字符串的文档.但这没有帮助.

在将字符串传递给coreNLP之前,如何从字符串中删除这些字符?

更新(11月16日):

为了完整起见,我应该提一下,我只是为了通过预处理文件来避免大量的错误消息而问这个问题.CoreNLP只是忽略它无法处理的字符,所以这不是问题.

Yan*_*off 7

在某种程度上,Mukesh KumarGsusRecovery提供的答案都有帮助,但并不完全正确.

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

似乎取代了所有无效的字符.但CoreNLP似乎不再支持.我通过在整个语料库上运行解析器来手动计算出来,这导致了这个:

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

所以现在我replaceAll()在将文档交给解析器之前运行两个命令.完整的代码片段是

// 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<HasWord> sentence : tokenizer) {
    List<TaggedWord> tagged = tagger.tagSentence(sentence);
    GrammaticalStructure gs = parser.predict(tagged);
    System.err.println(gs);
}
Run Code Online (Sandbox Code Playgroud)

但这不一定是不受支持的字符的完整列表,这就是我在GitHub上打开问题的原因.

请注意,CoreNLP会自动删除那些不受支持的字符.我想预处理语料库的唯一原因是避免所有这些错误消息.

11月27日更新

克里斯托弗曼宁刚刚回答了我打开的GitHub问题.有几种方法可以使用该类处理这些字符edu.stanford.nlp.process.TokenizerFactory;.以此代码示例来标记文档:

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
}
Run Code Online (Sandbox Code Playgroud)

您可以noneDelete在第4行中替换其他选项.我引用曼宁:

"(...)完整的六个选项组合,组合是否记录无,第一个或全部的警告,以及是否删除它们或将它们作为单个字符标记包含在输出中:noneDelete,firstDelete,allDelete, noneKeep,firstKeep,allKeep."

这意味着,要保留字符而不获取所有这些错误消息,最好的方法是使用该选项noneKeep.这种方式比任何删除这些字符的尝试都更优雅.