全文检索高亮工具类

来源:互联网 发布:串口监视软件 编辑:程序博客网 时间:2024/05/17 03:23

全文检索高亮工具类

—— Ivan / iu软件(www.iusofts.com)

  • 利用pinyin4j将汉字转换为拼音
  • 检索内容高亮(支持关键词高亮、被截取后的关键词高亮、同音关键词高亮)

1.高亮主工具类

package com.iusoft.sys.utils;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern;import org.apache.commons.lang.StringUtils;/** * 高亮工具类 *  * @author Ivan * @version 2.1 *  * 功能描述: *        1.普通高亮  *        2.同音高亮  *        3.汉字拼音混合高亮 *        4.自动合并 *        5.智能截取 */public class HighlightUtil {    public static void main(String[] args) {        // String content = "2015年被市场称为国企改革的“落地年”。市场时常会失控,所以要时常把握市场。";        String content="姓名:张三  拼音:zhangsan";        String keyword[]="zhangsan".split(" ");        //String content = "市场时常会失控,所以要时常把握市场。";        //String keyword[] = "市场 suoyi".split(" ");        System.out.println(contentHighlight(content, keyword, true, 0));    }    /**     * 检索内容高亮     *      * @param content     *            内容     * @param keywords     *            搜索关键词     * @param isHomophony     *            是否同音     * @param maxLength     *            最大长度(0为不限制)     * @return     */    public static String contentHighlight(String content, String keywords[],            boolean isHomophony, int maxLength) {        String cutContent = "";// 参照未截取内容        boolean isCut = false;        // 1.根据最大长度截取内容        if (maxLength > 0) {            if (StringUtils.isNotBlank(content) && content.length() > maxLength) {                cutContent = content.substring(0, maxLength);                isCut = true;            }        }        try {            List<Postion> list = new ArrayList<Postion>();// 所有匹配下标位置的集合            // 2.遍历关键词-匹配所有关键词下标位置            for (int i = 0; i < keywords.length; i++) {                if (StringUtils.isNotBlank(keywords[i].trim())) {                    list.addAll(getAllIndex(content, keywords[i], isHomophony));                }            }            // 3.下标集合-并集处理            if (isCut) {// 是否被截取                //如果文本内容已被截取,更新关键词在文本中正确的结束下标位置                for (int i = 0; i < list.size();) {                    if (list.get(i).start > maxLength - 1) {//如果关键词的开始位置大于截取长度                        list.remove(i);//移除无效下标位置                    } else {                        //如果关键词开始下标在截取范围内,结束下标在截取范围外,将结束下标改为文本最大下标                        if (list.get(i).end > maxLength - 1)                            list.get(i).end = maxLength - 1;                        i++;                    }                }            }            // 3.1 合并下标位置            for (int i = 0; i < list.size(); i++) {                for (int j = i + 1; j < list.size(); j++) {                    list.get(i).union(list.get(j));                }            }            // 3.2 去除被合并的下标位置            for (int i = 0; i < list.size();) {                if (list.get(i).isUnion()) {                    list.remove(i);                } else {                    i++;                }            }            // 4.替换文本标签-关键词高亮            // 4.1 按下标开始位置从小到大排序            Collections.sort(list, new Comparator<Postion>() {                public int compare(Postion arg0, Postion arg1) {                    return arg0.start - arg1.start;                }            });            // 4.2给文本中关键词添加高亮标红的闭合标签            String font = "<font color='red'>";            String font2 = "</font>";            if (isCut)                content = cutContent;            for (int i = 0; i < list.size(); i++) {                int be = i * (font.length() + font2.length());// 被标签占用的位置                content = content.substring(0, be + list.get(i).start)                        + font                        + content.substring(be + list.get(i).start,                                be + list.get(i).end + 1)                        + font2                        + content.substring(be + list.get(i).end + 1,                                content.length());            }        } catch (Exception e) {            System.out.println("高亮处理错误!");            e.printStackTrace();            if(isCut)return cutContent+"...";        }        return isCut?content+"...":content;    }    /**     * 获取关键词匹配下标     *      * @author:Ivan     * @date:2015年11月3日 上午10:53:31     * @param content     * @param str     * @param isHomophony     * @return     */    public static List<Postion> getAllIndex (String content, String str,            boolean isHomophony) throws Exception{        String cs[] = content.split("");        String strs[] = { "", str.toUpperCase() };        if (isChinese(str)) {            strs = str.split("");        }        // 所有匹配的下标位置集合        List<Postion> list = new ArrayList<Postion>();        Postion point = null; // 用来存储匹配的开始下标、结束下标        if (isHomophony) {// 如果同音,将每一项转换成拼音            // 将内容转换成拼音            for (int i = 1; i < cs.length; i++) {                if (StringUtils.isNotBlank(cs[i].trim())) {                    cs[i] = PinyinTool.toPinYin(cs[i]);                }            }            // 将关键词转成拼音            for (int i = 1; i < strs.length; i++) {                if (StringUtils.isNotBlank(strs[i].trim())) {                    strs[i] = PinyinTool.toPinYin(strs[i]);                }            }            if (isChinese(str)) {// 纯汉字匹配                for (int i = 1; i < cs.length; i++) {                    int count = 0;// 成果匹配次数                    if (i + strs.length - 1 > cs.length)                        break;// 剩余匹配个数不足时跳出                    for (int j = 1; j < strs.length; j++) {                        if (cs[i + j - 1].equals(strs[j]))                            count++;                    }                    // 当关键词的每一项都匹配时添加匹配下标                    if (count == strs.length - 1) {                        point = new Postion(i - 1, i - 1 + strs.length - 2);                        list.add(point);                    }                }                //获取拼音关键词在文本中所有下标位置                String index = getAllIndex(content.toUpperCase(), PinyinTool.toPinYin(str), 0);                if(StringUtils.isNotBlank(index)){                    // System.out.println(index);                    String indexs[] = index.split(",");                    for (int i = 0; i < indexs.length; i++) {                        int n = Integer.parseInt(indexs[i]);//开始下标位置                        point = new Postion(n, n+PinyinTool.toPinYin(str).length() - 1);                        list.add(point);                    }                }            } else {// 混合匹配                //获取拼音关键词在文本中所有下标位置                String index = getAllIndex(PinyinTool.toPinYin(content.toUpperCase()), strs[1], 0);                if(StringUtils.isNotBlank(index)){                    // System.out.println(index);                    String indexs[] = index.split(",");                    //处理逻辑:                    //  如果拼音关键词开始位置是文本内容中某个拼音的开始位置,并且拼音关键词的结束位置是文本内容中某个拼音的结束位置,                    //视为有效关键词,并记录该拼音关键词的开始下标和结束下标。                    int count = 0;//成功匹配次数,两次为有效匹配,否则为无效                    for (int i = 0; i < indexs.length; i++) {                        int n = Integer.parseInt(indexs[i]);//开始下标位置                        int sum = 0;//下标累计                        int start = 0;//开始下标                        int end = 0;//结束下标                        for (int j = 1; j < cs.length; j++) {                            if (n == sum && count == 0) {//满足开始位置,成功匹配一次                                count = 1;                                start = j;                            }                            sum += cs[j].length();//累加文本下标位置                            if (n + strs[1].length() == sum && count == 1) {//满足结束位置,成功匹配两次                                count = 2;                                end = j;                                break;                            }                        }                        if (count == 2) {//成功匹配两次,保存有效起始下标位置                            point = new Postion(start - 1, end - 1);                            list.add(point);                        }                        count = 0;//初始化匹配次数                    }                }            }        }else{            //获取拼音关键词在文本中所有下标位置            String index = getAllIndex(content.toUpperCase(), str, 0);            if(StringUtils.isNotBlank(index)){                // System.out.println(index);                String indexs[] = index.split(",");                for (int i = 0; i < indexs.length; i++) {                    int n = Integer.parseInt(indexs[i]);//开始下标位置                    point = new Postion(n, n+str.length() - 1);                    list.add(point);                }            }        }        // System.out.println("关键词:" + strs[1]);        return list;    }    /**     * 获取字符串匹配下标     *      * @author:Ivan     * @date:2015年11月3日 上午10:53:13     * @param content     * @param str     * @param index     * @return     */    public static String getAllIndex(String content, String str, int index) {        int n = content.indexOf(str, index);        if (n != -1) {            // 递归匹配所有下标位置            return n + "," + getAllIndex(content, str, n + 1);        } else {            return "";        }    }    /**     * 判断关键词是否为汉字     *      * @author:Ivan     * @date:2015年11月3日 下午3:05:55     * @param str     * @return     */    public static boolean isChinese(String str) {        String regex = "^[\u4e00-\u9fa5]+$";        return str.matches(regex);    }    /**     * 判断关键词是否包含汉字     *      * @author:Ivan     * @date:2015年11月3日 下午3:05:55     * @param str     * @return     */    public static boolean isContainsChinese(String str) {        Pattern p = Pattern.compile("[\u4e00-\u9fa5]");        Matcher m = p.matcher(str);        if (m.find()) {            return true;        }        return false;    }}

2.位置标记类

package com.iusoft.sys.utils;import java.util.HashSet;import java.util.Set;/** * 位置标记 *  * @author:Ivan * @date: 2015年11月3日 下午12:45:08 */class Postion {    public int start = 0;// 开始位置    public int end = 0;// 结束位置    private boolean isUnion=false;//是否被合并    public Postion() {    }    public Postion(int start, int end) {        this.start = start;        this.end = end;    }    /**     * 位置合并     *      * @author:Ivan     * @date:2015年11月3日 下午12:51:04     * @param postion     * @return     */    @SuppressWarnings("serial")    public boolean union(Postion postion) {        boolean b = false;        if (postion != null) {            Set<Integer> result = new HashSet<Integer>();            Set<Integer> set1 = new HashSet<Integer>() {                {                    for (int i = start; i <= end; i++) {                        add(i);                    }                }            };            final int s = postion.start, e = postion.end;            Set<Integer> set2 = new HashSet<Integer>() {                {                    for (int i = s; i <= e; i++) {                        add(i);                    }                }            };            //1.取交集            result.clear();            result.addAll(set1);            result.retainAll(set2);            if (result.size() > 0 ||this.end==postion.start-1 || this.start+1==postion.end) {//判断是否存在交集,存在交集的情况下执行并集操作                //2.取并集                result.clear();                result.addAll(set1);                result.addAll(set2);                for (Integer integer : set2) {                    if (integer < start)                        start = integer;                    if (integer > end)                        end = integer;                }                b = true;                postion.setUnion(b);//标记被合并            }        }        return b;    }    public int getStart() {        return start;    }    public void setStart(int start) {        this.start = start;    }    public int getEnd() {        return end;    }    public void setEnd(int end) {        this.end = end;    }    public boolean isUnion() {        return isUnion;    }    public void setUnion(boolean isUnion) {        this.isUnion = isUnion;    }    @Override    public String toString() {        return start+","+end+":"+isUnion;    }}

3.拼音工具类

package com.iusoft.sys.utils;import net.sourceforge.pinyin4j.PinyinHelper;import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;import java.util.Arrays;/** * 拼音工具类 * @author:Ivan * @date: 2015年11月3日 下午6:22:47 */public class PinyinTool {    static HanyuPinyinOutputFormat format = null;    public static enum Type {        UPPERCASE,              //全部大写        LOWERCASE,              //全部小写        FIRSTUPPER              //首字母大写    }    static{        format = new HanyuPinyinOutputFormat();        format.setCaseType(HanyuPinyinCaseType.UPPERCASE);        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);    }    public PinyinTool(){        format = new HanyuPinyinOutputFormat();        format.setCaseType(HanyuPinyinCaseType.UPPERCASE);        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);    }    public static String toPinYin(String str){        return toPinYin(str, "", Type.UPPERCASE);    }    public static String toPinYin(String str,String spera){        return toPinYin(str, spera, Type.UPPERCASE);    }    /**     * 将str转换成拼音,如果不是汉字或者没有对应的拼音,则不作转换     * 如: 明天 转换成 MINGTIAN     * @param str     * @param spera     * @return     * @throws BadHanyuPinyinOutputFormatCombination     */    public static String toPinYin(String str, String spera, Type type) {        if(str == null || str.trim().length()==0)            return "";        if(type == Type.UPPERCASE)            format.setCaseType(HanyuPinyinCaseType.UPPERCASE);        else            format.setCaseType(HanyuPinyinCaseType.LOWERCASE);        String py = "";        String temp = "";        String[] t=null;        for(int i=0;i<str.length();i++){            char c = str.charAt(i);            if((int)c <= 128)                py += c;            else{                try {                    t = PinyinHelper.toHanyuPinyinStringArray(c, format);                } catch (BadHanyuPinyinOutputFormatCombination e) {                    e.printStackTrace();                }                if(t == null)                    py += c;                else{                    temp = t[0];                    if(type == Type.FIRSTUPPER)                        temp = t[0].toUpperCase().charAt(0)+temp.substring(1);                    py += temp+(i==str.length()-1?"":spera);                }            }        }        return py.trim();    }}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 阴毛囊炎怎么引起的 脚痛风是怎么引起的 寻常疣是什么引起的 脂肪瘤是怎么引起的 脑垂体瘤是什么引起的 腰痛是什么原因引起的 坐骨神经痛怎么引起的 传染性软疣怎么引起的 左背痛是什么原因引起的 脑供血不足是怎么引起的 手臂发麻是什么原因引起的 小腿浮肿是什么原因引起的 腰椎管狭窄怎么引起的 脚后跟疼是什么原因引起的 腿痛有哪些原因引起 末梢神经炎怎么引起的 腿浮肿是什么原因引起的 血糖高是什么原因引起的 腰椎滑脱是什么引起的 坐骨神经痛是怎么引起的 肾功能不全怎么引起的 腰困是什么原因引起的 腰肌劳损是怎么引起的 泡疹是什么原因引起的 嘴唇疱疹是怎么引起的 肾功能衰竭是怎么引起的 带状疱疹是什么引起 坐骨神经痛是怎样引起的 病毒性软疣怎么引起的 坐骨神经疼是什么引起的 坐骨神经是怎么引起的 腰椎管狭窄是什么引起的 病毒性疱疹怎么引起的 衣原体感染怎么引起的 颈椎痛是什么原因引起的 腰部带状疱疹是怎么引起的 妇科囊肿是什么引起的 胆囊息肉是什么引起的 阴毛囊炎是怎么引起的 急性咽炎是什么引起的 面部神经炎怎么引起的