想写BLOG,又不知道写些什么(只是最近刚想是不是该写个自已的BLOG)。于是乎,把以前曾经在项目中用到的一个东东写上了,个人愚见:).
使用LUCENE时,搜索'c++'这样的词会出现空的结果.原因肯定是在创建索引时出了问题,创建索引就需要分词,你没搜到'C++',就是因为没有c++这样一个分词加到索引中.
说完就开工,我仿照英文的分词方式,每个字母做一个分词,也就是'c++'被分成'c' '+' '+'三个,然后加在索引中.
public sealed class ChineseTokenizer : Tokenizer
{
public ChineseTokenizer(TextReader _in)
{
input = _in;
}

private int offset = 0;//偏移量
private int bufferIndex = 0;////词汇在缓冲中的位置
private int dataLen = 0;//缓冲字符的长度
private static int MAX_WORD_LEN = 255;
private static int IO_BUFFER_SIZE = 1024;
private char[] buffer = new char[MAX_WORD_LEN];
private char[] ioBuffer = new char[IO_BUFFER_SIZE];

private int length;//词汇的长度
private int start;//开始偏移量.

private void Push(char c)
{

if (length == 0) start = offset - 1; // 分词起始位置
buffer[length++] = Char.ToLower(c); // 加入缓冲区

}

private Token Flush()
{

if (length > 0)
{
return new Token(new String(buffer, 0, length), start, start + length);
}
else
return null;
}

public override Token Next()
{
length = 0;
start = offset;

while (true)
{
char c;
offset++;

if (bufferIndex >= dataLen)
{
dataLen = input.Read(ioBuffer, 0, ioBuffer.Length);
bufferIndex = 0;
};

if (dataLen == 0) return Flush();
else
c = ioBuffer[bufferIndex++];

if (c == ','
|| c == ','
|| c == ';'
|| c == ';')//排除字符, ; ,;参与分词
{
if (length > 0) return Flush();
continue;
}
switch (Char.GetUnicodeCategory(c))
{
case UnicodeCategory.DecimalDigitNumber://指示字符是十进制数字;即在范围 0 到 9 内
case UnicodeCategory.LowercaseLetter://指示字符是小写字母
case UnicodeCategory.UppercaseLetter://指示字符是大写字母
Push(c);
if (length == MAX_WORD_LEN) return Flush();
break;
case UnicodeCategory.MathSymbol://指示字符是数学符号,例如“+”或“=”。
case UnicodeCategory.OpenPunctuation://指示字符是成对的标点符号(例如括号、方括号和大括号)之一的开始字符
case UnicodeCategory.ClosePunctuation://指示字符是成对的标点符号(例如括号、方括号和大括号)之一的封闭字符
case UnicodeCategory.CurrencySymbol://货币符号
case UnicodeCategory.DashPunctuation://指示字符是短划线或连字符
case UnicodeCategory.ModifierSymbol://指示字符是修饰符符号,这指示环绕的字符的修改 例如:^
case UnicodeCategory.OtherPunctuation://指示字符是标点,但它不是连接符标点、短划线标点、开始标点、结束标点、前引号标点或后引号标点,如:%
case UnicodeCategory.OtherLetter:
if (length > 0)
{
bufferIndex--;
offset--;
return Flush();
}
Push(c);
return Flush();

default:
if (length > 0)
{
return Flush();
}
break;
}
}

}
}
这是最主要的分词,你可以自已设置想要参与分词的字符,放到你的Analyzer中使用吧.
顺便贴一下网上的ChineseAnalyzer,为了配合使用,改过后如下:
public sealed class ChineseFilter : TokenFilter
{
public static String[] STOP_WORDS =
{
"and", "are", "as", "at", "be", "but", "by",
"for", "if", "in", "into", "is", "it",
"no", "not", "of", "on", "or", "such",
"that", "the", "their", "then", "there", "these",
"they", "this", "to", "was", "will", "with"
};

private Hashtable stopTable;

public ChineseFilter(TokenStream _in) : base (_in)
{
stopTable = new Hashtable(STOP_WORDS.Length);

for (int i = 0; i < STOP_WORDS.Length; i++)
stopTable[STOP_WORDS[i]] = STOP_WORDS[i];
}

public override Token Next()
{

for (Token token = input.Next(); token != null; token = input.Next())
{
String text = token.TermText();

if (stopTable[text] == null)
{
return token;

}

}
return null;
}
}

public class ChineseAnalyzer : Analyzer
{

public ChineseAnalyzer()
{
}

public override sealed TokenStream TokenStream(String fieldName, TextReader reader)
{
TokenStream result = new ChineseTokenizer(reader);
result = new ChineseFilter(result);
return result;
}
}
使用LUCENE时,搜索'c++'这样的词会出现空的结果.原因肯定是在创建索引时出了问题,创建索引就需要分词,你没搜到'C++',就是因为没有c++这样一个分词加到索引中.
说完就开工,我仿照英文的分词方式,每个字母做一个分词,也就是'c++'被分成'c' '+' '+'三个,然后加在索引中.






































































































顺便贴一下网上的ChineseAnalyzer,为了配合使用,改过后如下:




















































