2014-06-16 112 views
0

我已經得到完全相同的問題this thread,所以我打開一個新的問題。很抱歉,所有人都回答了鏈接的話題,BTW。Lucene TokenStream異常

所以:我試圖避免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

你的問題是,你是消費在過濾一切,傳遞迴從createComponents調用之前關閉它。

你是,我認爲,試圖調試分析如何與這個工程:

try { 
    shiFilter.reset(); 
    while(shiFilter.incrementToken()) { 
     token = cta.toString(); 
     System.out.println(token); 
    } 
    shiFilter.end(); 
    shiFilter.close(); 
} 
catch (IOException ioe) { 
    ioe.printStackTrace(); 
} 

但是請注意,當你用它做,shiFilter位於流的結束,並已關閉。您現在將它從方法傳回給TokenStreamComponents,當Lucene現在將嘗試使用它來索引文檔。它將首先調用reset(),並將拋出指示的異常,以嘗試使用已關閉的資源。

如果你想調試這個,我建議你只是創建一個自定義分析器的實例,並且調用analyzer.tokenStream來獲取調試輸出的流。如果您確實需要通過遍歷過濾器實例而不是分析器來進行調試,則需要構建一個獨立的實例,而不是使用createComponents中的流。

+0

因此,如果我理解正確,將這段代碼放入createComponents中會涉及「重置」的不正確使用,即重置已關閉的資源。這說得通。 然後,我必須移動我的自定義分析器所在的那個部分。無論如何,我的目的不是調試。我想創建自定義標記,例如選擇某些詞的鄰域。我認爲我應該把它做成createComponents。 – PatrickBateman1981

+0

如果你想做一些處理來修改(或添加或刪除)分析中的標記,你應該實現一個['TokenFilter'](http://lucene.apache.org/core/4_8_0/core/org/apache/lucene的/分析/ TokenFilter。html),並將它添加到你的過濾器鏈中(就像你的'ShingleFilter'或'StopFilter'一樣)。 – femtoRgon

+0

那麼我應該做的唯一事情就是重寫'TokenFilter'抽象類中的'incrementToken'方法嗎? – PatrickBateman1981

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(); 
    } 
} 

}

+0

感謝您的回覆。 – PatrickBateman1981

+0

您是否能夠獲得預期的產出? – Debasis

+0

我會嘗試,然後給予反饋。 無論如何:我的目的是分析令牌的鄰域以獲得個性化的N-gram。例如,如果我的標記與前綴詞列表匹配,則在前後添加2或3個標記。就像,考慮到「狐狸」的標誌,讓「棕色的狐狸跳過」或類似。 – PatrickBateman1981