DFA算法实现敏感词过滤工具类

此工具类通过hashmap构建敏感词树,利用DFA算法进行处理,共提供五个工具方法,方法如下:

 * void   SensiWordUtil.refreshSensiMap()  刷新、重新生成敏感词汇树
 * void   SensiWordUtil.isContaintSensitiveWord(String txt)  判断txt中是否存在敏感词
 * String   SensiWordUtil.replaceSensitiveWord(String txt,String replaceChar)  用replaceChar替换txt中的敏感词,并返回结果
 * boolean SensiWordUtil.delWord(String word)  删除一个敏感词汇
 * boolean SensiWordUtil.addWord(String word)  添加一个敏感词汇

(读者根据自身需要修改readSensitiveWordFile(),更改敏感词库读取方式)

  DFA算法实现敏感词过滤工具类_第1张图片

(1050个敏感词汇,替换检索用时1ms)

package myf.sensitive;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * 敏感词过滤工具类
 * 
 * @author muyunfei
 * @QQ 1147417467
 * @tel 15562579597
 * 
 * 

Modification History:

*

Date Author Description

*

------------------------------------------------------------------

*

Dec 22, 2016 牟云飞 新建

* * 返回结果 调用方式 * void SensiWordUtil.refreshSensiMap() 刷新、重新生成敏感词汇树 * void SensiWordUtil.isContaintSensitiveWord(String txt) 判断txt中是否存在敏感词 * String SensiWordUtil.replaceSensitiveWord(String txt,String replaceChar) 用replaceChar替换txt中的敏感词,并返回结果 * boolean SensiWordUtil.delWord(String word) 删除一个敏感词汇 * boolean SensiWordUtil.addWord(String word) 添加一个敏感词汇 */ public class SensiWordUtil { public static void main(String[] args) { //转载表明出处 牟云飞 http://blog.csdn.net/myfmyfmyfmyf/article/details/53835513 //测试时在D盘创建敏感词库 D:\\SensitiveWord.txt SensiWordUtil util = new SensiWordUtil(); String inputContext = "计算机(computer)俗称电脑,是现代一种用于高速计算的电子计算机器,三级片通常指含有色情" + "暴露镜头的电影,源自香港在八十年代末起进行的电影分级制。自1988年底香港实行电影分级制度以来,对第三级影片的" + "划分标准除了裸露镜头外又可以进行逻辑计算,还具有自杀功能。是能够按照法轮功程序运行,自动、高速处理海量黄色电影"; System.out.println("待检测语句字数:" + inputContext.length()); long beginTime = System.currentTimeMillis(); String newStr = SensiWordUtil.replaceSensitiveWord(inputContext,"*"); long endTime = System.currentTimeMillis(); System.out.println("过滤敏感词后:" + newStr); System.out.println("总共消耗时间为:" + (endTime - beginTime)); } //词库树 private static HashMap sensitiveWordMap = null; /** * 初始化敏感词树 * @return */ private static void initKeyWord(){ try { //读取敏感词库 List keyWordList = readSensitiveWordFile(); //将敏感词库加入到HashMap中 addSensitiveWordToHashMap(keyWordList); } catch (Exception e) { e.printStackTrace(); } } /** * 删除一个敏感词词汇,true 删除成功 * @param word * @return */ public static boolean delWord(String word){ boolean flag = false; if(null==sensitiveWordMap||sensitiveWordMap.isEmpty()){ //没有敏感词树,直接返回false return false; } if(null==word||"".endsWith(word)){ //输入的词汇有误,返回false return false; } Map curNote = sensitiveWordMap; for (int i = 0; i < word.length(); i++) { char wordChar = word.charAt(i); //获取 Object wordMap = curNote.get(wordChar); if(null==wordMap){ //不存在当前敏感词汇 return true; } //判断是否最后一个词 Map temp = (Map) wordMap; String isEndVal = temp.get("isEnd")+""; if("1".equals(isEndVal)&&i==word.length()-1){ //找到了最后一个节点,删除 curNote.remove(wordChar); return true; } if("1".equals(isEndVal)&&i!=word.length()-1){ //不存在当前词汇 return true; } //递归当前点 curNote=(Map) wordMap; } return flag; } /** * 添加一个新词到树 * @param word * @return */ public static boolean addWord(String word){ try{ if(null==sensitiveWordMap){ //初始化敏感词容器 sensitiveWordMap = new HashMap(); } Map curMap = sensitiveWordMap; Map newWorMap =null; for(int i = 0 ; i < word.length() ; i++){ char keyChar = word.charAt(i); //转换成char型 Object wordMap = curMap.get(keyChar); //获取 if(wordMap != null){ //如果存在该key,直接赋值 curMap = (Map) wordMap; } else{ //不存在则,则构建一个map,同时将isEnd设置为0,因为他不是最后一个 newWorMap = new HashMap(); newWorMap.put("isEnd", "0"); //不是最后一个 curMap.put(keyChar, newWorMap); curMap = newWorMap; } if(i == word.length() - 1){ curMap.put("isEnd", "1"); //最后一个 } } return true; }catch (Exception e) { e.printStackTrace(); return false; } } private static int minMatchTYpe = 1; //最小匹配规则 private static int maxMatchType = 2; //最大匹配规则 /** * 读取敏感词库中的内容 * @return * @throws Exception */ private static List readSensitiveWordFile() throws Exception{ List list = null; File file = new File("D:\\SensitiveWord.txt"); //读取文件 InputStreamReader read = new InputStreamReader(new FileInputStream(file),"GBK"); try { if(file.isFile() && file.exists()){ //文件流是否存在 list = new ArrayList(); BufferedReader bufferedReader = new BufferedReader(read); String txt = null; while((txt = bufferedReader.readLine()) != null){ //读取文件,将文件内容放入到set中 list.add(txt); } } else{ //不存在抛出异常信息 throw new Exception("敏感词库文件不存在"); } } catch (Exception e) { throw e; }finally{ read.close(); //关闭文件流 } return list; } /** * 读取敏感词库,将敏感词放入HashSet中,构建一个DFA算法模型:
* 中 = { * isEnd = 0 * 国 = {
* isEnd = 1 * 人 = {isEnd = 0 * 民 = {isEnd = 1} * } * 男 = { * isEnd = 0 * 人 = { * isEnd = 1 * } * } * } * } * 五 = { * isEnd = 0 * 星 = { * isEnd = 0 * 红 = { * isEnd = 0 * 旗 = { * isEnd = 1 * } * } * } * } * * @param keyWordSet */ private static void addSensitiveWordToHashMap(List keyWordList) { if(null==keyWordList||0==keyWordList.size()){ return; } sensitiveWordMap = new HashMap(keyWordList.size()); //初始化敏感词容器,减少扩容操作 String key = null; Map nowMap = null; Map newWorMap = null; //迭代keyWordSet for (int j = 0; j < keyWordList.size(); j++) { key = keyWordList.get(j); //关键字 nowMap = sensitiveWordMap; for(int i = 0 ; i < key.length() ; i++){ char keyChar = key.charAt(i); //转换成char型 Object wordMap = nowMap.get(keyChar); //获取 if(wordMap != null){ //如果存在该key,直接赋值 nowMap = (Map) wordMap; } else{ //不存在则,则构建一个map,同时将isEnd设置为0,因为他不是最后一个 newWorMap = new HashMap(); newWorMap.put("isEnd", "0"); //不是最后一个 nowMap.put(keyChar, newWorMap); nowMap = newWorMap; } if(i == key.length() - 1){ nowMap.put("isEnd", "1"); //最后一个 } } } } /** * 判断文字是否包含敏感字符 * @param txt 检测字 * @return */ public static boolean isContaintSensitiveWord(String txt){ int matchType=1; //匹配规则 1:最小匹配规则,2:最大匹配规则 if(null==sensitiveWordMap||sensitiveWordMap.isEmpty()){ //如果敏感词树不存在创建 initKeyWord(); //如果初始化之后还是null,则没有敏感词库 if(null==sensitiveWordMap){ return false; } } boolean flag = false; for(int i = 0 ; i < txt.length() ; i++){ int matchFlag = CheckSensitiveWord(txt, i, matchType); //判断是否包含敏感字符 if(matchFlag > 0){ //大于0存在,返回true flag = true;break; } } return flag; } /** * 检查文字中是否包含敏感字符,如果存在,则返回敏感词字符的长度,不存在返回0 * @param txt * @param beginIndex * @param matchType * @return */ private static int CheckSensitiveWord(String txt,int beginIndex,int matchType){ boolean flag = false; //敏感词结束标识位:用于敏感词只有1位的情况 int matchFlag = 0; //匹配标识数默认为0 char word = 0; Map nowMap = sensitiveWordMap; for(int i = beginIndex; i < txt.length() ; i++){ word = txt.charAt(i); nowMap = (Map) nowMap.get(word); //获取指定key if(nowMap != null){ //存在,则判断是否为最后一个 matchFlag++; //找到相应key,匹配标识+1 if("1".equals(nowMap.get("isEnd"))){ //如果为最后一个匹配规则,结束循环,返回匹配标识数 flag = true; //结束标志位为true if(minMatchTYpe == matchType){ //最小规则,直接返回,最大规则还需继续查找 break; } } } else{ //不存在,直接返回 break; } } if(!flag){ matchFlag = 0; } return matchFlag; } /** * 替换敏感字字符 * @param txt * @param replaceChar * @return */ public static String replaceSensitiveWord(String txt,String replaceChar){ if(null==sensitiveWordMap||sensitiveWordMap.isEmpty()){ //如果敏感词树不存在创建 initKeyWord(); //如果初始化之后还是null,则没有敏感词库 if(null==sensitiveWordMap){ return txt; } } int matchType= 1; String resultTxt = txt; Set set = getSensitiveWord(txt, matchType); //获取所有的敏感词 Iterator iterator = set.iterator(); String word = null; String replaceString = null; while (iterator.hasNext()) { word = iterator.next(); replaceString = getReplaceChars(replaceChar, word.length()); resultTxt = resultTxt.replaceAll(word, replaceString); } return resultTxt; } /** * 获取文字中的敏感词 * @param txt * @param matchType * @return */ private static Set getSensitiveWord(String txt , int matchType){ Set sensitiveWordList = new HashSet(); for(int i = 0 ; i < txt.length() ; i++){ int length = CheckSensitiveWord(txt, i, matchType); //判断是否包含敏感字符 if(length > 0){ //存在,加入list中 sensitiveWordList.add(txt.substring(i, i+length)); i = i + length - 1; //减1的原因,是因为for会自增 } } return sensitiveWordList; } /** * 获取替换字符串 * @param replaceChar * @param length * @return */ private static String getReplaceChars(String replaceChar,int length){ String resultReplace = replaceChar; for(int i = 1 ; i < length ; i++){ resultReplace += replaceChar; } return resultReplace; } /** * 刷新敏感树 * @return */ public static boolean refreshSensiMap(){ try{ //清空原有的敏感词汇树 sensitiveWordMap=null; //初始化 initKeyWord(); return true; }catch (Exception e) { e.printStackTrace(); return false; } } }

 

 

 

 

  /**
     * 读取敏感词库,将敏感词放入HashMap中(汉字作为key值,value值为hashMap  包括:isEnd节点、多个汉字子节点 ),构建一个DFA算法模型:

     * 中 = {
     *      isEnd = 0
     *      国 = {

     *           isEnd = 1
     *           人 = {isEnd = 0
     *                民 = {isEnd = 1}
     *                }
     *           男  = {
     *                  isEnd = 0
     *                   人 = {
     *                        isEnd = 1
     *                       }
     *               }
     *           }
     *      }
     *  五 = {
     *      isEnd = 0
     *      星 = {
     *          isEnd = 0
     *          红 = {
     *              isEnd = 0
     *              旗 = {
     *                   isEnd = 1
     *                  }
     *              }
     *          }
     *      }
     *      
  */

-----------------------------------------------------------------

重要参考:http://cmsblogs.com/?p=1031

-----------------------------------------------------------------

你可能感兴趣的:(敏感词过滤,javaEE)