Lucene IKAnalyzer(V2012)

IKAnalyzer:IK分词器,采用特有的“正向迭代最细粒度切分算法”,支持细粒度和智能分词两种切分方式。

支持中文、数字、中文词汇等分词处理,兼容韩文、日语字符。

例子:主要展示细粒度和智能分词两种切分方式的不同。

Analyzer analyzer = new IKAnalyzer(); //默认构造函数是细粒度切分
还有一种构造函数:

Analyzer analyzer = new IKAnalyzer(true);//为true时支持智能切分,false为细粒度切分

细粒度:

package com.xuzengqiang.design.common.lucene.demo;

import java.io.IOException;
import java.io.StringReader;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.wltea.analyzer.lucene.IKAnalyzer;

/**
 * 描述:IKAnalyzer
 * @author xuzengqiang
 */
public class IKAnalyzerDemo {

	public static void main(String[] args) {
		String words = "IKAnalyzer是一个开源的, 基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始,IKAnalyzer已经推出了3个大版本。";
		Analyzer analyzer = new IKAnalyzer();
		StringReader reader = new StringReader(words);
		TokenStream token = null;
		try {
			// 直接这样写会抛出java.lang.IllegalStateException: TokenStream contract
			// violation: reset()/close() call missing,
			// reset() called multiple times, or subclass does not call
			// super.reset(). Please see Javadocs of
			// TokenStream class for more information about the correct
			// consuming workflow.可以查看TokenStream
			// API在使用incrementToken()之前必须先reset()一次
			token = analyzer.tokenStream("", reader);
			CharTermAttribute term = token.getAttribute(CharTermAttribute.class);
			token.reset();
			// 遍历分词数据
			while (token.incrementToken()) {
				System.out.print(term.toString() + "|");
			}
			token.end();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			destroyResource(token, reader);
		}
		System.out.println();
	}

	public static void destroyResource(TokenStream token, StringReader reader) {
		try {
			if (token != null) {
				token.close();
			}
			if (reader != null) {
				reader.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

打印结果:

ikanalyzer|是|一个|一|个|开源|的|基于|java|语言|开发|的|轻量级|量级|的|中文|分词|工具包|工具|包|从|2006|年|12|月|推出|1.0|版|开始|ikanalyzer|已经|推出|出了|3|个|大|版本|

当将构造函数换成new IKAnalyzer(true);之后打印:

ikanalyzer|是|一个|开源|的|基于|java|语言|开发|的|轻量级|的|中文|分词|工具包|从|2006年|12月|推出|1.0版|开始|ikanalyzer|已经|推|出了|3个|大|版本|

另外也可以使用这种方式分词:

package com.xuzengqiang.design.common.lucene.demo;

import java.io.IOException;
import java.io.StringReader;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;
import org.wltea.analyzer.lucene.IKAnalyzer;

/**
 * 描述:IKAnalyzer
 * @author xuzengqiang
 */
public class KAnalyzerDemoTwo {

	public static void main(String[] args) {
		String words = "IKAnalyzer是一个开源的, 基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始,IKAnalyzer已经推出了3个大版本。";
		StringReader reader = new StringReader(words);
		IKSegmenter segmenter = new IKSegmenter(reader, true);
		Lexeme lexeme = null;
		try {
			while ((lexeme = segmenter.next()) != null) {
				System.out.print(lexeme.getLexemeText() + "|");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println();
	}
}

IKsegementer:IK分词器的核心类。

public IKSegmenter(Reader input , boolean useSmart) 
参数1:字符输入读取,userSmart:是否采用智能切分策略,true:智能切分,false:最细粒度切分。

public IKSegmentation(Reader input , Configuration cfg)
参数2:分词器配置,用户可以定制自己的Configuration,来改变词典的配置。

public synchronized Lexeme next()throws IOException
读取分词器切分出来的下一个语义单元。为null分词结束。
Luxeme语义单元对象,类似于Lucene Token.

public int getBeginPosition()
获取语义单元的起始字符在文本中的位置。

public int getEndPosition() 
获取语义单元结束字符的下一个位置。

public int getLength()
获取语义单元包含字符串的长度。

public String getLexemeText() 
获取语义单元包含字符串的内容。


IKAnalyzer扩展字典配置,需要配置IKAnalyzer.cfg.xml文件,放在源文件目录下:

分词器的词典文件格式是无BOM 的UTF-8 编码的中文文本文件,文件扩展名不限。词典中,每个中文词汇独立占一行,使用\r\n 的DOS 方式换行。可以参考jar包下面的main2012.dic文件。推荐与配置文件放在同一目录下。

IKAnalyzer.cfg.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">  
<properties>  
    <comment>IKAnalyzer扩展配置</comment>
    <!-- 扩展字典: -->
    <entry key="ext_dict">vnetoo_directory.dic</entry> 
    <!-- 扩展停止词字典:排除对该关键字的搜索    -->
    <entry key="ext_stopwords">vnetoo_stopword.dic</entry> 
</properties>
自定义扩展字典vnetoo_directory.dic:

互联天下
许增强
艾贞堆
何亚飞
自定义扩展停止词字典:vnetoo_stopword.dic

的
是
或
或者
那么这个时候就可以看到分词器中不会包含该关键词了,且能够分出自定义的词了:

package com.xuzengqiang.design.common.lucene.demo;

import java.io.IOException;
import java.io.StringReader;

import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;

/**
 * 描述:IKAnalyzer
 * @author xuzengqiang
 */
public class KAnalyzerDemoTwo {

	public static void main(String[] args) {
		String words = "许增强或者何亚飞的杯子";
		StringReader reader = new StringReader(words);
		IKSegmenter segmenter = new IKSegmenter(reader, true);
		Lexeme lexeme = null;
		try {
			while ((lexeme = segmenter.next()) != null) {
				System.out.print(lexeme.getLexemeText() + "|");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		System.out.println();
	}
}
打印结果:

加载扩展词典:vnetoo_directory.dic
加载扩展停止词典:vnetoo_stopword.dic
许增强|何亚飞|杯子|

如果配置了配置自定义的扩展词库,可能有时候操作不需要使用,这个时候我们可以实现Configuration类,如果不需要使用,那么返回对应的getExtDictionarys()和getExtStopWordDictionarys() 为空即可。

package com.vnetoo.redu.common.lucene;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.InvalidPropertiesFormatException;
import java.util.List;
import java.util.Properties;

import org.wltea.analyzer.cfg.Configuration;

/**
 * 描述:IKAnalyzer配置文件.需要实现Configuration接口
 * 主要提供各种词典的文件路径
 * 单例模式
 * @author xuzengqiang
 * @since 2015-1-14 13:53:56
 */
public class IKConfiguration implements Configuration {

	/**
	 * 描述:主词典目录
	 */
	private static final String PATH_DIC_MAIN = "org/wltea/analyzer/dic/main2012.dic";
	/**
	 * 描述:量词词典目录
	 */
	private static final String PATH_DIC_QUANTIFIER = "org/wltea/analyzer/dic/quantifier.dic";
	/**
	 * 描述:配置文件目录
	 */
	private static final String FILE_NAME = "IKAnalyzer.cfg.xml";
	/**
	 * 描述:扩展词典key名称
	 */
	private static final String EXT_DICT = "ext_dict";
	/**
	 * 描述:禁用词典的key名称
	 */
	private static final String EXT_STOP = "ext_stopwords";
	/**
	 * 描述:配置文件属性对象
	 */
	private Properties props;
	/**
	 * 描述:是否使用智能分词
	 */
	private boolean useSmart;
	/**
	 * 描述:是否使用扩展停止词典(默认使用)
	 */
	private boolean useStopword = Boolean.TRUE;
	/**
	 * 描述:是否使用扩展词典(默认使用)
	 * @return
	 */
	private boolean useDict = Boolean.TRUE;

	/**
	 * 描述:提供外部接口
	 * @return
	 */
	public static IKConfiguration getInstance() {
		return new IKConfiguration();
	}

	/**
	 * 描述:配置文件读取
	 */
	private IKConfiguration() {
		this.props = new Properties();
		InputStream input = super.getClass().getClassLoader().getResourceAsStream(FILE_NAME);
		if (input == null)
			return;
		try {
			this.props.loadFromXML(input);
		} catch (InvalidPropertiesFormatException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public boolean useSmart() {
		return this.useSmart;
	}

	public void setUseSmart(boolean useSmart) {
		this.useSmart = useSmart;
	}

	public boolean isUseDict() {
		return useDict;
	}

	public void setUseDict(boolean useDict) {
		this.useDict = useDict;
	}

	public boolean isUseStopword() {
		return useStopword;
	}

	public void setUseStopword(boolean useStopword) {
		this.useStopword = useStopword;
	}
	
	/**
	 * 描述:获取主词典目录
	 */
	public String getMainDictionary() {
		return "org/wltea/analyzer/dic/main2012.dic";
	}

	/**
	 * 描述:获取量词词典目录
	 */
	public String getQuantifierDicionary() {
		return "org/wltea/analyzer/dic/quantifier.dic";
	}

	/**
	 * 描述:获取扩展词典的路径,当不需要使用扩展词典,返回空
	 */
	public List<String> getExtDictionarys() {
		if (!isUseDict()) {
			return null;
		}
		List<String> extDictFiles = new ArrayList<String>(2);
		String extDictCfg = this.props.getProperty("ext_dict");
		if (extDictCfg != null) {
			String[] filePaths = extDictCfg.split(";");
			if (filePaths != null) {
				for (String filePath : filePaths) {
					if ((filePath != null) && (!("".equals(filePath.trim())))) {
						extDictFiles.add(filePath.trim());
					}
				}
			}
		}
		return extDictFiles;
	}

	/**
	 * 描述:获取禁止词典的路径.当不需要使用时返回空
	 */
	public List<String> getExtStopWordDictionarys() {
		if (!isUseStopword()) {
			return null;
		}
		List<String> extStopWordDictFiles = new ArrayList<String>(2);
		String extStopWordDictCfg = this.props.getProperty("ext_stopwords");
		if (extStopWordDictCfg != null) {
			String[] filePaths = extStopWordDictCfg.split(";");
			if (filePaths != null) {
				for (String filePath : filePaths) {
					if ((filePath != null) && (!("".equals(filePath.trim())))) {
						extStopWordDictFiles.add(filePath.trim());
					}
				}
			}
		}
		return extStopWordDictFiles;
	}
}

使用方法:

package com.xuzengqiang.design.common.lucene.demo;

import java.io.IOException;
import java.io.StringReader;

import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;

/**
 * 描述:IKAnalyzer
 * @author xuzengqiang
 */
public class KAnalyzerDemoTwo {

	public static void main(String[] args) {
		String words = "许增强或者何亚飞的杯子";
		StringReader reader = new StringReader(words);
		IKConfiguration config = IKConfiguration.getInstance();
		config.setUseDict(false);
		config.setUseStopword(false);
		IKSegmenter segmenter = new IKSegmenter(reader, config);
		Lexeme lexeme = null;
		try {
			while ((lexeme = segmenter.next()) != null) {
				System.out.print(lexeme.getLexemeText() + "|");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		System.out.println();
	}
}

或者可以使用下面这种方式,推荐:

package com.xuzengqiang.design.common.lucene.demo;

import java.io.IOException;
import java.io.StringReader;

import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;
import org.wltea.analyzer.dic.Dictionary;

/**
 * 描述:IKAnalyzer
 * @author xuzengqiang
 */
public class KAnalyzerDemoTwo {

	public static void main(String[] args) {
		IKConfiguration config = IKConfiguration.getInstance();
		config.setUseDict(false);
		config.setUseStopword(false);
		config.setUseSmart(false);
		Dictionary.initial(config);

		String words = "许增强或者何亚飞的杯子";
		StringReader reader = new StringReader(words);
		IKSegmenter segmenter = new IKSegmenter(reader, true);
		Lexeme lexeme = null;
		try {
			while ((lexeme = segmenter.next()) != null) {
				System.out.print(lexeme.getLexemeText() + "|");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		System.out.println();
	}
}
这种方式对第一中分词方式仍然适用:

package com.xuzengqiang.design.common.lucene.demo;

import java.io.IOException;
import java.io.StringReader;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.wltea.analyzer.dic.Dictionary;
import org.wltea.analyzer.lucene.IKAnalyzer;

/**
 * 描述:IKAnalyzer
 * @author xuzengqiang
 */
public class IKAnalyzerDemo {

	public static void main(String[] args) {
		IKConfiguration config = IKConfiguration.getInstance();
		config.setUseDict(false);
		config.setUseStopword(false);
		Dictionary.initial(config);
		
		String words = "游戏小苹果青花瓷";
		Analyzer analyzer = new IKAnalyzer();
		StringReader reader = new StringReader(words);
		TokenStream token = null;
		try {
			CharTermAttribute term = token.getAttribute(CharTermAttribute.class);
			token.reset();
			// 遍历分词数据
			while (token.incrementToken()) {
				System.out.print(term.toString() + "|");
			}
			token.end();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			destroyResource(token, reader);
		}
		System.out.println();
	}

	public static void destroyResource(TokenStream token, StringReader reader) {
		try {
			if (token != null) {
				token.close();
			}
			if (reader != null) {
				reader.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值