Lucene TokenStream例外

时间:2014-06-16 13:06:11

标签: java exception lucene token tokenize

我有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 );

但错误最后。有什么建议吗?

2 个答案:

答案 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中使用流。