Lucene 3.0.0 的TokenStream与Analyzer

2022-09-15 17:51:16 浏览数 (3)

大家好,又见面了,我是你们的朋友全栈君。

如果你看的Lucene相关的书是很老版本的, 比如说2.4或者更早, 那么对于这个版本中的Analyzer可能就不那么容易接受了, 我也是看的<lucene分析与应用>这本书, 比较古老的版本.

今天读了一下源代码, 大概说说心得, 我从SimpleAnalyzer说起.

SimpleAnalyzer的作用就是把一段字符串中除了符号和非文字的内容作为分隔, 把句子分成很多的单词. 对于中文也可以用来剔除标点符号

代码语言:javascript复制
public TokenStream tokenStream(String fieldName, Reader reader) {
代码语言:javascript复制
  return new LowerCaseTokenizer(reader);
代码语言:javascript复制
}

SimpleAnalyzer的TokenStream就是调用了LowerCaseTokenizer的构造函数. LowerCaseTokenizer继承自CharTokenizer. 首先来看看CharTokenizer的构造函数吧:

代码语言:javascript复制
public CharTokenizer(Reader input) {
代码语言:javascript复制
  super(input);
代码语言:javascript复制
  offsetAtt = addAttribute(OffsetAttribute.class);
代码语言:javascript复制
  termAtt = addAttribute(TermAttribute.class);
代码语言:javascript复制
}

除了调用基类的构造函数外(继承自Tokenizer), 另外还有下面两个与Attribute相关的语句, Attribute是Lucene新增的内容(具体是不是3.0新增的就不清楚了), 作用是可以在TokenStream中加入一些用户需要的内容, 比如说单词的词性, 文字等等内容, 这些东西是可以用户定义的, 提供了更多的耦合性, 怎么访问这些内容我上一篇日志也是有说的.

下面我把CharTokenizer的incrementToken()函数的代码贴出来分析一下

代码语言:javascript复制
public final boolean incrementToken() throws IOException {
代码语言:javascript复制
  clearAttributes();
代码语言:javascript复制
  int length = 0;
代码语言:javascript复制
  int start = bufferIndex;
代码语言:javascript复制
  char[] buffer = termAtt.termBuffer();
代码语言:javascript复制
  while (true) {
代码语言:javascript复制
代码语言:javascript复制
    if (bufferIndex >= dataLen) {
代码语言:javascript复制
      offset  = dataLen;
代码语言:javascript复制
      dataLen = input.read(ioBuffer);
代码语言:javascript复制
      if (dataLen == -1) {
代码语言:javascript复制
        dataLen = 0;                            // so next offset  = dataLen won't decrement offset
代码语言:javascript复制
        if (length > 0)
代码语言:javascript复制
          break;
代码语言:javascript复制
        else
代码语言:javascript复制
          return false;
代码语言:javascript复制
      }
代码语言:javascript复制
      bufferIndex = 0;
代码语言:javascript复制
    }
代码语言:javascript复制
代码语言:javascript复制
    final char c = ioBuffer[bufferIndex  ];
代码语言:javascript复制
代码语言:javascript复制
    if (isTokenChar(c)) {               // if it's a token char
代码语言:javascript复制
代码语言:javascript复制
      if (length == 0)                 // start of token
代码语言:javascript复制
        start = offset   bufferIndex - 1;
代码语言:javascript复制
      else if (length == buffer.length)
代码语言:javascript复制
        buffer = termAtt.resizeTermBuffer(1 length);
代码语言:javascript复制
代码语言:javascript复制
      buffer[length  ] = normalize(c); // buffer it, normalized
代码语言:javascript复制
代码语言:javascript复制
      if (length == MAX_WORD_LEN)      // buffer overflow!
代码语言:javascript复制
        break;
代码语言:javascript复制
代码语言:javascript复制
    } else if (length > 0)             // at non-Letter w/ chars
代码语言:javascript复制
      break;                           // return 'em
代码语言:javascript复制
  }
代码语言:javascript复制
代码语言:javascript复制
  termAtt.setTermLength(length);
代码语言:javascript复制
  offsetAtt.setOffset(correctOffset(start), correctOffset(start length));
代码语言:javascript复制
  return true;
代码语言:javascript复制
}

在一个Tokenizer里面将保留这多个Attribute的实例, 这些实例是循环利用的, 每新得到一个单词, 就改写一下他们的内容,

1)

代码语言:javascript复制
if (bufferIndex >= dataLen) {
代码语言:javascript复制
  offset  = dataLen;
代码语言:javascript复制
  dataLen = input.read(ioBuffer);
代码语言:javascript复制
  if (dataLen == -1) {
代码语言:javascript复制
    dataLen = 0;                            // so next offset  = dataLen won't decrement offset
代码语言:javascript复制
    if (length > 0)
代码语言:javascript复制
      break;
代码语言:javascript复制
    else
代码语言:javascript复制
      return false;
代码语言:javascript复制
  }
代码语言:javascript复制
  bufferIndex = 0;
代码语言:javascript复制
}

这段代码是初始化的内容, 得到整个字符串的长度, ioBuffer就是这个字符串

2)

代码语言:javascript复制
final char c = ioBuffer[bufferIndex  ];
代码语言:javascript复制
代码语言:javascript复制
if (isTokenChar(c)) {               // if it's a token char
代码语言:javascript复制
代码语言:javascript复制
  if (length == 0)                 // start of token
代码语言:javascript复制
    start = offset   bufferIndex - 1;
代码语言:javascript复制
  else if (length == buffer.length)
代码语言:javascript复制
    buffer = termAtt.resizeTermBuffer(1 length);
代码语言:javascript复制
代码语言:javascript复制
  buffer[length  ] = normalize(c); // buffer it, normalized
代码语言:javascript复制
代码语言:javascript复制
  if (length == MAX_WORD_LEN)      // buffer overflow!
代码语言:javascript复制
    break;
代码语言:javascript复制
代码语言:javascript复制
} else if (length > 0)             // at non-Letter w/ chars
代码语言:javascript复制
  break;                           // return 'em

这段代码是不停的读取下一个字符, 看看是符号还是合法的字符.

3)

代码语言:javascript复制
termAtt.setTermLength(length);
代码语言:javascript复制
offsetAtt.setOffset(correctOffset(start), correctOffset(start length));
代码语言:javascript复制
return true;

最后把单词的termAtt和offsetAtt赋值, 返回

转载于:https://www.cnblogs.com/LeftNotEasy/archive/2010/01/17/1650139.html

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/163122.html原文链接:https://javaforall.cn

0 人点赞