我有this thread完全相同的问题,所以我开了一个新问题。很抱歉所有人都回答了链接的帖子,BTW。
所以:我正在努力避免java.lang.IllegalStateException:TokenStream合同违规。
我的代码非常类似于上面链接的代码:
protected TokenStreamComponents createComponents( String fieldName, Reader reader ) {
String token;
CharArraySet stopWords = new CharArraySet( Version.LUCENE_48, 0, false );
stopWords.addAll( StopAnalyzer.ENGLISH_STOP_WORDS_SET );
keepWords.addAll( getKeepWordList() );
Tokenizer source = new StandardTokenizer( Version.LUCENE_48, reader );
TokenStream filter = new StandardFilter( Version.LUCENE_48, source );
filter = new StopFilter( Version.LUCENE_48, filter, stopWords );
ShingleFilter shiFilter = new ShingleFilter( filter, 2, 3 );
CharTermAttribute cta = shiFilter.addAttribute( CharTermAttribute.class );
try {
shiFilter.reset();
while( shiFilter.incrementToken() ) {
token = cta.toString();
System.out.println( token );
}
shiFilter.end();
shiFilter.close();
}
catch ( IOException ioe ) {
ioe.printStackTrace();
}
return new TokenStreamComponents( source, filter );
}
我不明白建议的解决方案:它是什么意思“简单地构建一个新的TokenStream”或“重置读者”?我尝试了两种解决方案,例如添加:
source.setReader( reader );
或改为:
filter = new StopFilter( Version.LUCENE_48, filter, stopWords );
ShingleFilter shiFilter = new ShingleFilter( filter, 2, 3 );
但错误最后。有什么建议吗?
答案 0 :(得分:0)
我完全不明白你想要做什么。我相信除了unigrams之外,你还想从令牌流中获取bigrams和trigrams。下面的代码片段(我在对代码进行一些清理后开发的代码片段)为我运行,是执行此操作的标准方法。
import java.io.*;
import org.apache.lucene.analysis.core.*;
import org.apache.lucene.analysis.*;
import org.apache.lucene.analysis.ngram.NGramTokenFilter;
import org.apache.lucene.analysis.shingle.ShingleFilter;
import org.apache.lucene.analysis.standard.*;
import org.apache.lucene.util.*;
import org.apache.lucene.analysis.util.*;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
class TestAnalyzer extends Analyzer {
TestAnalyzer() {
super();
}
protected TokenStreamComponents createComponents( String fieldName, Reader reader ) {
String token;
TokenStream result = null;
Tokenizer source = new StandardTokenizer( Version.LUCENE_CURRENT, reader );
result = new ShingleFilter(source, 2, 3);
return new TokenStreamComponents( source, result );
}
}
public class LuceneTest {
public static void main(String[] args) {
TestAnalyzer analyzer = new TestAnalyzer();
try {
TokenStream stream = analyzer.tokenStream("field", new StringReader("This is a damn test."));
CharTermAttribute termAtt = stream.addAttribute(CharTermAttribute.class);
stream.reset();
// print all tokens until stream is exhausted
while (stream.incrementToken()) {
System.out.println(termAtt.toString());
}
stream.end();
stream.close();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
答案 1 :(得分:0)
您的问题是,您正在使用过滤器中的所有内容并关闭它,然后再将其从createComponents
调用中传回。
我认为,您试图调试分析的工作方式:
try {
shiFilter.reset();
while( shiFilter.incrementToken() ) {
token = cta.toString();
System.out.println( token );
}
shiFilter.end();
shiFilter.close();
}
catch ( IOException ioe ) {
ioe.printStackTrace();
}
但请注意,完成后,shiFilter
位于流的末尾,并且已关闭。现在,当Lucene现在尝试使用它来索引文档时,您现在从TokenStreamComponents中的方法传回它。它将首先调用reset()
,并将尝试使用已经关闭的资源抛出指示的异常。
如果你想调试它,我建议你只创建自定义分析器的一个实例,并调用analyzer.tokenStream
来获取调试输出的流。如果你真的需要通过遍历过滤器实例而不是分析器进行调试,那么你需要构建一个独立的实例,而不是在createComponents
中使用流。