solr入门之pinyin4j源代码改写动态加入扩展词及整合进war项目中
1.初始化时载入用户定义的字典
package net.sourceforge.pinyin4j; import net.sourceforge.pinyin4j.multipinyin.Trie; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException; import com.gome.mx.plus.pinyin.ext.PYWriterUtils; /**
* Manage all external resources required in PinyinHelper class.
*
* @author Li Min (xmlerlimin@gmail.com)
*/
public class ChineseToPinyinResource {
/**
* A hash table contains <Unicode, HanyuPinyin> pairs
*/
private Trie unicodeToHanyuPinyinTable = null; /**
* @param unicodeToHanyuPinyinTable The unicodeToHanyuPinyinTable to set.
*/
private void setUnicodeToHanyuPinyinTable(Trie unicodeToHanyuPinyinTable) {
this.unicodeToHanyuPinyinTable = unicodeToHanyuPinyinTable;
} /**
* @return Returns the unicodeToHanyuPinyinTable.
*/
public Trie getUnicodeToHanyuPinyinTable() {
return unicodeToHanyuPinyinTable;
} /**
* Private constructor as part of the singleton pattern.
*/
private ChineseToPinyinResource() {
initializeResource();
} /**
* Initialize a hash-table contains <Unicode, HanyuPinyin> pairs
*/
private void initializeResource() {
try {
final String resourceName = "/pinyindb/unicode_to_hanyu_pinyin.txt";
final String resourceMultiName = "/pinyindb/multi_pinyin.txt";
final String userResourceName = PYWriterUtils.getPath(); setUnicodeToHanyuPinyinTable(new Trie());
getUnicodeToHanyuPinyinTable().load(ResourceHelper.getResourceInputStream(resourceName)); getUnicodeToHanyuPinyinTable().loadMultiPinyin(ResourceHelper.getResourceInputStream(resourceMultiName)); getUnicodeToHanyuPinyinTable().loadMultiPinyinExtend();
//载入用户自己定义词库
if (userResourceName != null) {
File userMultiPinyinFile = new File(userResourceName);
FileInputStream is = new FileInputStream(userMultiPinyinFile);
getUnicodeToHanyuPinyinTable().load(is);
} } catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
} Trie getHanyuPinyinTrie(char ch) { String codepointHexStr = Integer.toHexString((int) ch).toUpperCase(); // fetch from hashtable
return getUnicodeToHanyuPinyinTable().get(codepointHexStr);
} /**
* Get the unformatted Hanyu Pinyin representations of the given Chinese
* character in array format.
*
* @param ch given Chinese character in Unicode
* @return The Hanyu Pinyin strings of the given Chinese character in array
* format; return null if there is no corresponding Pinyin string.
*/
String[] getHanyuPinyinStringArray(char ch) {
String pinyinRecord = getHanyuPinyinRecordFromChar(ch);
return parsePinyinString(pinyinRecord);
} String[] parsePinyinString(String pinyinRecord) { if (null != pinyinRecord) {
int indexOfLeftBracket = pinyinRecord.indexOf(Field.LEFT_BRACKET);
int indexOfRightBracket = pinyinRecord.lastIndexOf(Field.RIGHT_BRACKET); String stripedString =
pinyinRecord.substring(indexOfLeftBracket + Field.LEFT_BRACKET.length(),
indexOfRightBracket); return stripedString.split(Field.COMMA); } else
return null; // no record found or mal-formatted record
} /**
* @param record given record string of Hanyu Pinyin
* @return return true if record is not null and record is not "none0" and
* record is not mal-formatted, else return false
*/
private boolean isValidRecord(String record) {
final String noneStr = "(none0)"; return (null != record) && !record.equals(noneStr) && record.startsWith(Field.LEFT_BRACKET)
&& record.endsWith(Field.RIGHT_BRACKET);
} /**
* @param ch given Chinese character in Unicode
* @return corresponding Hanyu Pinyin Record in Properties file; null if no
* record found
*/
private String getHanyuPinyinRecordFromChar(char ch) {
// convert Chinese character to code point (integer)
// please refer to http://www.unicode.org/glossary/#code_point
// Another reference: http://en.wikipedia.org/wiki/Unicode
int codePointOfChar = ch; String codepointHexStr = Integer.toHexString(codePointOfChar).toUpperCase(); // fetch from hashtable
Trie trie = getUnicodeToHanyuPinyinTable().get(codepointHexStr);
String foundRecord = null;
if (trie != null)
foundRecord = trie.getPinyin(); return isValidRecord(foundRecord) ? foundRecord : null;
} /**
* Singleton factory method.
*
* @return the one and only MySingleton.
*/
public static ChineseToPinyinResource getInstance() { return ChineseToPinyinResourceHolder.theInstance;
} /**
* Singleton implementation helper.
*/
private static class ChineseToPinyinResourceHolder {
static final ChineseToPinyinResource theInstance = new ChineseToPinyinResource();
} /**
* A class encloses common string constants used in Properties files
*
* @author Li Min (xmlerlimin@gmail.com)
*/
class Field {
static final String LEFT_BRACKET = "("; static final String RIGHT_BRACKET = ")"; static final String COMMA = ",";
}
}
批量写入功能加入 package com.gome.mx.plus.pinyin.ext; import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; import javax.xml.crypto.dsig.spec.ExcC14NParameterSpec; import net.sourceforge.pinyin4j.ChineseToPinyinResource;
import net.sourceforge.pinyin4j.ResourceHelper;
import net.sourceforge.pinyin4j.multipinyin.MultiPinyinConfig;
import net.sourceforge.pinyin4j.multipinyin.Trie;
/**
* 将汉语和拼音写入指定的文件里--文件位置能够指定
* 而且能够动态的载入 不须要重新启动服务
* 还能指定是否又一次写 还是追加的方式
* 还能够将原来已经存在的拼音合并过来--能够指定
* @author songqinghu
*
*/
public class PYWriterUtils { //这里改为系统的绝对路径
private static String path; private static boolean flag = true;//能够设置文件位置
/**
* @描写叙述:获取配置文件的位置 ---仅仅能设置一次
* @return void
* @exception
* @createTime:2016年4月6日
* @author: songqinghu
*/
public static void setPath(String path){
if(flag){
PYWriterUtils.path = path;
flag = false;//仅仅能设置 一次
}
} public static String getPath(){
return PYWriterUtils.path;
} private static Class pathClass = PYWriterUtils.class; /**
*
* @描写叙述:默认写入的方式 设置为追加模式 合并已经存在的拼音为一个
* @param word 汉字
* @param pinyin 拼音
* @param voice 声调
* @return
* @return boolean 是否成功
* @exception
* @createTime:2016年4月6日
* @author: songqinghu
* @throws Exception
*/
public static boolean dufaultWriter(String word,String pinyin,Integer voice) throws Exception{
return writerControler(word, pinyin, voice, true, true);
}
/**
*
* @描写叙述:能够设置的写入方式 --这里还要添加一个批量写入的功能 本方法仅仅是处理一个汉字
* @param word 汉字
* @param pinyin 拼音
* @param voice 声调
* @param additional 是否追加到文件后
* @param merge 是否合并已经出现的拼音到文件里
* @return
* @return boolean
* @exception
* @createTime:2016年4月6日
* @author: songqinghu
* @throws Exception
* 龦
*/
public static boolean writerControler(String word,String pinyin,Integer voice,
boolean additional ,boolean merge) throws Exception{ String path = PYWriterUtils.path;
if (path != null) {
File userMultiPinyinFile = new File(path);
if (userMultiPinyinFile.exists()) {
//获取
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(userMultiPinyinFile, additional)));
//加入音调
pinyin = pinyin + voice;
//写入--16进制 查询 --
if(word !=null && word.length()>0){
char c = word.toCharArray()[0];
if(c>128){//是汉字
String unicode = Integer.toHexString(c).toUpperCase();//编码
if(merge){//假设要合并
Trie trie = ChineseToPinyinResource.getInstance().getUnicodeToHanyuPinyinTable(); if(trie.get(unicode)!=null){ //存在了编码和拼音相应关系---这里最好在推断一次是否存在了该拼音
String before = trie.get(unicode).getPinyin();
before = before.trim().substring(1, before.trim().length()-1);//去除()
//存在了 就不加入进去了
boolean flag = false;
String[] words = before.split(",");
for (String str : words) {
if(str.equals(pinyin)){
flag = true; //存在该拼音
break;
}
}
if(flag){
pinyin = before;
}else{
pinyin = before +Field.COMMA+ pinyin ;
}
}
//不存在 不须要改变pinyin
}
pinyin = addSymbol(pinyin);
writer.write(unicode+Field.SPACE+pinyin);
writer.newLine();
}
}
writer.flush();
writer.close();
//写入完毕 更新词库
reloadText();
return true;
}
}else{
throw new Exception("找不到用户扩展字典");
}
return false;
} /**
* 完毕批量加入的功能
*/
/**
*
* @描写叙述:批量加入汉字和拼音的映射关系到自己定义词库中----这里有个问题 当 批量输入一个多音字 拼音都是map中同一个key时仅仅能提交成功一个--建议提交两次
* @param contents 汉字 拼音 音调 这里一个汉字 能够输入多个拼音了
* @param additional 是否追加到文件后
* @param merge 是否合并已经出现的拼音到文件里
* @return
* @return boolean
* @exception
* @createTime:2016年4月7日
* @author: songqinghu
*/
public static boolean writerBatch(Map<String,Map<String,Integer>> contents,boolean additional ,boolean merge){
//载入文件部分
BufferedWriter writer =null;
try {
if (path != null) {
File userMultiPinyinFile = new File(path);
if (userMultiPinyinFile.exists()) {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(userMultiPinyinFile, additional)));
//写入处理部分
Set<Entry<String, Map<String, Integer>>> entrySet = contents.entrySet();
for (Entry<String, Map<String, Integer>> entry : entrySet) {
String word = entry.getKey().trim();//汉语
String pinyin = "";
for (Entry<String, Integer> content : entry.getValue().entrySet()) {
String py = content.getKey().trim();
Integer voice = content.getValue();
pinyin = pinyin + py + voice+",";
}
//拼音加入结束 去除最后一个,
pinyin = pinyin.substring(0, pinyin.length()-1);
//汉字和拼音都已经处理完毕 进入单个词语写入模块 --方法 抽取出来公用
String line = midWriter(word, pinyin, merge);
if(line != null){
writer.write(line);
writer.newLine();
}
}
writer.flush();
return true;
}
}else{
throw new Exception("请配置用户词典绝对路径");
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(writer!=null)
writer.close();
PYWriterUtils.reloadText();
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
/**
*
* @描写叙述:方法抽取--对单个字进行处理
* @return
* @return String 组合后的一行要写入的 形式 E4A3 (ang3,yi1,wang3)
* @exception
* @createTime:2016年4月7日
* @author: songqinghu
*/
private static String midWriter(String word ,String pinyin,boolean merge){ if(word !=null && word.length()>0){
char c = word.toCharArray()[0];
if(c>128){//假设是汉字
String unicode = Integer.toHexString(c).toUpperCase();//变为16进制
if(merge){//假设要合并 须要先取出来 在合并 取不到还要处理一下
//获取到总的资源池
Trie trie = ChineseToPinyinResource.getInstance().getUnicodeToHanyuPinyinTable();
//假设存在该词语的拼音
if(trie.get(unicode)!=null &&trie.get(unicode).getPinyin()!=null){
String before = trie.get(unicode).getPinyin();
//对已经处在字符串进行处理 --(xxx) (xxxx,xxxx)
before = before.trim().substring(1, before.trim().length()-1);//去除()
//假设存在了 就不再反复加入了
String[] splits = before.split(",");
String[] strings = pinyin.trim().split(",");
Set<String> temp = new HashSet<String>();
//去反复
for (String split : splits) {
temp.add(split.trim());
}
for (String string : strings) {
temp.add(string);
}
pinyin ="";
for (String tem : temp) {
pinyin = pinyin + tem+Field.COMMA;
}
pinyin = pinyin.substring(0,pinyin.length()-1);//去除最后一个,
}
//不存在 直接 保持拼音不变
}
//组合成写入的格式
pinyin = addSymbol(pinyin); return unicode + Field.SPACE+pinyin;
}
}
return null;
} /**
*
* @描写叙述:默认批量写入功能
* @param contents
* @return
* @return boolean
* @exception
* @createTime:2016年4月7日
* @author: songqinghu
*/
public static boolean defaultWriterBatch(Map<String,Map<String,Integer>> contents){ return writerBatch(contents, true, true);
} /**
*
* @描写叙述:当自己定义文件须要更新时,调用方法 又一次载入自己的配置文件
* @return
* @return boolean
* @exception
* @createTime:2016年4月6日
* @author: songqinghu
* @throws IOException
*/
public static boolean reloadText() throws IOException{ if (path != null) {
File userMultiPinyinFile = new File(path);
FileInputStream is = new FileInputStream(userMultiPinyinFile);
if(is !=null){
ChineseToPinyinResource.getInstance().getUnicodeToHanyuPinyinTable().load(is);
return true;
}
}
return false;
} /**
* 加入操作符号
*/
private static String addSymbol(String pinyin){
return Field.LEFT_BRACKET+pinyin+Field.RIGHT_BRACKET;
} class Field {
static final String LEFT_BRACKET = "("; static final String RIGHT_BRACKET = ")"; static final String COMMA = ","; static final String SPACE = " ";
}
}
将jar和原有suggestproject进行整合 出现故障---无法写入jar中自己定义文件(jar中的文件仅仅能读取)
===>解决思路 将用户自己定义词典放在执行的warproject中 须要手动指定一次文件位置---大概功能已经能够整合进入项目中使用了 package cn.com.mx.gome.suggest.controller; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import com.gome.mx.plus.pinyin.ext.PYReadUtils;
import com.gome.mx.plus.pinyin.ext.PYWriterUtils; import cn.com.mx.gome.search.core.common.ResultData;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; /**
*
* @author songqinghu
* 对pinyin4j中的用户自己定义词典库进行操作
*/
@Controller
@RequestMapping("/suggest/pinyin")
public class PinYinController { private Logger logger = LoggerFactory.getLogger(PinYinController.class); /**
*
* @描写叙述:获取指定汉字的现存词库中的拼音 --须要POST请求
* @return
* @return ResultData<String>
* @exception
* @createTime:2016年4月7日
* @author: songqinghu
*/
@RequestMapping("/getpy")
@ResponseBody
public ResultData<List<String>> getPinYin(String word){
ResultData<List<String>> result = new ResultData<List<String>>();
try {
if(word != null && word.trim().length()>0){
String[] fullPY = PYReadUtils.getFullPY(word);
if(fullPY!=null && fullPY.length>0){
ArrayList<String> list = new ArrayList<String>();
for (String string : fullPY) {
list.add(string);
}
result.setData(list);
result.setSuccess(true);
return result;
} } } catch (BadHanyuPinyinOutputFormatCombination e) {
logger.error("",e);
}
result.setSuccess(false);
return result;
}
/**
*
* @描写叙述:加入一个汉字的映射关系到用户自定库中
* @param word
* @param pinyin
* @param voice
* @return
* @return ResultData<String>
* @exception
* @createTime:2016年4月7日
* @author: songqinghu
*/
@RequestMapping("/addpy")
@ResponseBody
public ResultData<Boolean> addPinYin(String word,String pinyin,Integer voice){
ResultData<Boolean> result = new ResultData<Boolean>();
if(word!=null && word.trim().length()>0 && pinyin !=null && pinyin.trim().length()>0&&voice>0){
try {
boolean flag = PYWriterUtils.dufaultWriter(word, pinyin, voice);
result.setData(flag);
result.setSuccess(true);
return result;
} catch (Exception e) {
e.printStackTrace();
logger.error("",e);
}
}
result.setSuccess(false);
return result;
} @RequestMapping("/test")
@ResponseBody
public ResultData<Boolean> addtest(String word,String pinyin,Integer voice){
Map<String, Map<String, Integer>> contents = new HashMap<String,Map<String,Integer>>(); HashMap<String, Integer> content = new HashMap<String,Integer>(); content.put("test", 1);
content.put("tttt", 2);
content.put("ling", 1);
contents.put("〇", content);
// setDicPath();
ResultData<Boolean> result = new ResultData<Boolean>();
if(word!=null && word.trim().length()>0 && pinyin !=null && pinyin.trim().length()>0&&voice>0){
try {
boolean flag = PYWriterUtils.defaultWriterBatch(contents);
result.setData(flag);
result.setSuccess(true);
return result;
} catch (Exception e) {
e.printStackTrace();
logger.error("",e);
}
}
result.setSuccess(false);
return result;
} }
warproject使用 SSM架构 项目启动时载入词库所在位置工具类 package cn.com.mx.gome.suggest.component;
/**
* 项目启动时载入指定的pinyin4j用户扩展字典
* @author songqinghu
*
*/ import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import com.gome.mx.plus.pinyin.ext.PYWriterUtils; import cn.com.mx.gome.suggest.controller.PinYinController; @Component
public class PinYinDataSourceFile { @Value("${PINYIN_FILE_PATH}")
private String path;
/**
*
* @描写叙述:项目启动时 此类载入完毕后运行此方法完毕用户自己定义pinyin4j字典配置的载入
* @return void
* @exception
* @createTime:2016年4月7日
* @author: songqinghu
*/
@PostConstruct
private void setFilePath(){
String pathFile = PinYinDataSourceFile.class.getResource(path).getPath();
PYWriterUtils.setPath(pathFile);
} }
最后附上 改写后的pinyin4j源代码
链接:http://pan.baidu.com/s/1skUD8dv password:fhy4
solr入门之pinyin4j源代码改写动态加入扩展词及整合进war项目中的更多相关文章
- Solr入门介绍
solr入门案例 solr是apache下的一个全文检索引擎系统. 我们需要在服务器上单独去部署solr, 通过它的客户端工具包solrJ, 就是一个 jar包, 集成到我们项目中来调用服务器中 ...
- solr入门教程-较详细
Solr调研总结 开发类型 全文检索相关开发 Solr版本 4.2 文件内容 本文介绍solr的功能使用及相关注意事项;主要包括以下内容:环境搭建及调试;两个核心配置文件介绍;维护索引;查询索引,和在 ...
- Solr入门(一)
一丶Solr入门1.Solr的启动Solr各版本下载老版本的时候,需要将war包放到tomcat中,现在只需解压,由于自带jetty容器,可以直接启动 [root@aaa bin]# ./solr s ...
- 后端技术杂谈4:Elasticsearch与solr入门实践
阮一峰:全文搜索引擎 Elasticsearch 入门教程 作者:阮一峰 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://g ...
- 如何把C++的源代码改写成C代码?而C改C++只需一步!
★ 如何把C++的源代码改写成C代码? C++解释器比C语言解释器占用的存储空间要大,想要在某些特定场合兼容C++代码,同时为了节省有限的存储空间,降低成本,也为了提高效率,将用C++语言写的源程序用 ...
- Solr入门之SolrServer实例化方式
随着solr版本的不断升级, 差异越来越大, 从以前的 solr1.2 到现在的 solr4.3, 无论是类还是功能都有很大的变换, 为了能及时跟上新版本的步伐, 在此将新版本的使用做一个简单的入门说 ...
- esri-leaflet入门教程(5)- 动态要素加载
esri-leaflet入门教程(5)- 动态要素加载 by 李远祥 在上一章节中已经说明了esr-leaflet是如何加载ArcGIS Server提供的各种服务,这些都是服务本身来决定的,API脚 ...
- MyBatis基础入门《二十》动态SQL(foreach)
MyBatis基础入门<二十>动态SQL(foreach) 1. 迭代一个集合,通常用于in条件 2. 属性 > item > index > collection : ...
- Apache Solr入门教程(初学者之旅)
Apache Solr入门教程(初学者之旅) 写在前面:本文涉及solr入门的各方面,建议边思考边实践,相信能帮助你对solr有个清晰全面的了解并能简单实用. 在Apache Solr初学者教程的这个 ...
随机推荐
- javascript作用域链理解
执行上下文(Execution context,简称EC) 概念 每当控制器到达ECMAScript可执行代码的时候,就进入了一个执行上下文. javascript中,EC分为三种: ...
- bzoj1093【ZJOI2007】最大半联通子图
题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1093 sol :一开始理解错题意了QAQ,还莫名其妙写挂了QAQ,调了半天 首先显然一个强联 ...
- 解决jsp在ios小屏手机下面滑动不流畅的问题
今天做好的静态文件发给后台改成jsp之后,发现原本流畅滑动的页面在iphone5下面变得一卡一卡的. 之后加上了 -webkit-overflow-scrolling: touch; 这个属性之后,成 ...
- 微信小程序 报警告的解决办法
wx:for 如果没有给它相应的 wx:key 控制台就会有警告,解决的办法给它添加相应的key警告就消失啦
- pat 团体天梯赛 L2-007. 家庭房产
L2-007. 家庭房产 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序给定每个人的家庭成员和其自己名下的房产,请你统计出每个家庭的人口数.人均房产面积及房产 ...
- POJ 1236 Network of Schools Tarjan缩点
Network of Schools Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 22729 Accepted: 89 ...
- POJ1195Mobile phones
二维树状数组板子题. #include<cstdio> #include<cstring> #include<iostream> #include<cstdl ...
- linux下的程序调试方法汇总
搞电子都知道,电路不是焊接出来的,是调试出来的.程序员也一定认同,程序不是写出来的,是调试出来的.那么调试工具就显得尤为重要,linux作为笔者重要的开发平台,在linux中讨论调试工具主要是为那些入 ...
- [原创] 树莓派个人实测 Q&A(最新修改使用windows连接远程桌面)
原文出处:http://www.eeboard.com/bbs/thread-5191-1-1.html 这篇帖子我打算用Q&A的方式来编写,这样大家更容易一目了然的看明整个帖子的内容,层次分 ...
- MMU介绍【转】
转自:http://blog.csdn.net/martree/article/details/3321578 虚拟存储器的基本思想是程序,数据,堆栈的总的大小可以超过物理存储器的大小,操作系统把当前 ...