2011-09-12 7 views
0

免責条項:私は過去41時間のうち36日間をコーディングしています。頭痛がします。なぜトークンフィルタを組み合わせて2つのトークンが返されているのか、ソースストリームの最初のトークンの両方がわかりません。Lucene TokenFilterの何が問題なのですか?

私はここに根本的な問題は、あなたがTokenCombiner、それが消費プロデューサー(入力)株の両方を実現し、同じ属性を再利用しなければならないということです!考える
public class TokenCombiner extends TokenFilter { 

    /* 
    * Recombines all tokens back into a single token using the specified delimiter. 
    */ 
    public TokenCombiner(TokenStream in, int delimiter) { 
    super(in); 
    this.delimiter = delimiter; 
    } 
    int delimiter; 


    private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class); 
    private final OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class); 


    private boolean firstToken = true; 
    int startOffset = 0; 
    @Override 
    public final boolean incrementToken() throws IOException { 
    while (true){ 
     boolean eos = input.incrementToken(); //We have to process tokens even if they return end of file. 
     CharTermAttribute token = input.getAttribute(CharTermAttribute.class); 
     if (eos && token.length() == 0) break; //Break early to avoid extra whitespace. 
     if (firstToken){ 
      startOffset = input.getAttribute(OffsetAttribute.class).startOffset(); 
      firstToken = false; 

     }else{ 
      termAtt.append(Character.toString((char)delimiter)); 
     } 
     termAtt.append(token); 
     if (eos) break; 
    } 
    offsetAtt.setOffset(startOffset, input.getAttribute(OffsetAttribute.class).endOffset()); 
    return false; 
    } 

    @Override 
    public void reset() throws IOException { 
    super.reset(); 
    firstToken = true; 
    startOffset = 0; 
    } 
} 

答えて

3

だからtoken == termAtt常に(アサートを追加しよう!)。あなたは週末に36時間コーディングされている場合は吸う

男は、...これを試してみてください。


public class TokenCombiner extends TokenFilter { 
    private final StringBuilder sb = new StringBuilder(); 
    private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class); 
    private final OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class); 
    private final char separator; 
    private boolean consumed; // true if we already consumed 

    protected TokenCombiner(TokenStream input, char separator) { 
    super(input); 
    this.separator = separator; 
    } 

    @Override 
    public final boolean incrementToken() throws IOException { 
    if (consumed) { 
     return false; // don't call input.incrementToken() after it returns false 
    } 
    consumed = true; 

    int startOffset = 0; 
    int endOffset = 0; 

    boolean found = false; // true if we actually consumed any tokens 
    while (input.incrementToken()) { 
     if (!found) { 
     startOffset = offsetAtt.startOffset(); 
     found = true; 
     } 
     sb.append(termAtt); 
     sb.append(separator); 
     endOffset = offsetAtt.endOffset(); 
    } 

    if (found) { 
     assert sb.length() > 0; // always: because we append separator 
     sb.setLength(sb.length() - 1); 
     clearAttributes(); 
     termAtt.setEmpty().append(sb); 
     offsetAtt.setOffset(startOffset, endOffset); 
     return true; 
    } else { 
     return false; 
    } 
    } 

    @Override 
    public void reset() throws IOException { 
    super.reset(); 
    sb.setLength(0); 
    consumed = false; 
    } 
} 
+0

ありがとう!現在のトークンが最後に使用可能なトークンであっても、incrementToken()はtrueを返すはずですか? (今のところ、TokenStreamの設計に関するドキュメントはありますか?javadocsには、このような詳細は含まれていません)。 –

+0

http://lucene.apache.org/java/3_3_0/api/core/org/の下にスクロールします。 apache/lucene/analysis/package-summary.htmlを参照し、http://lucene.apache.org/java/3_3_0/api/core/org/apache/lucene/analysis/TokenStream.htmlに記載されているワークフローをチェックしてください。ドキュメントにどのような詳細を追加するべきかを教えてください! –

関連する問題