Java 处理字符串中的敏感词 配置模式

最新有个小业务需要用到批量去除敏感词,调用量非常频繁且对性能要求较大,且关键字是随时会增加的,因此也就不能使用简单的替换,而是需用用到配置文件方式处理。

两个类,一段配置文件

1、初始化敏感词库,将敏感词加入到HashMap中,构建DFA算法模型

package com.zhx.guides.collect.util.object.word;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @Class SensitivewordFilter
 * @Author 作者姓名:
 * @Version 1.0
 * @Date 创建时间:2020-05-22 14:51
 * @Copyright Copyright by *** company
 * @Direction 类说明  敏感词过滤
 */
public class SensitivewordFilter {

    @SuppressWarnings("rawtypes")
    private static Map sensitiveWordMap = null;
    public static int minMatchTYpe = 1; //最小匹配规则
    public static int maxMatchType = 2; //最大匹配规则

    public static List datas ;


    static{
        if( datas == null ) {
           try {
               //从文件中读取词库中的内容,将内容添加到list集合中
               datas = SensitiveWordInit.readSensitiveWordFile();
               //初始化词库,读取敏感词库,将敏感词放入HashSet中,构建一个DFA算法模型:
               SensitiveWordInit.init(datas);
           }catch (Exception e){}
        }
    }

    private static void initSensitiveWord(List datas) {
        sensitiveWordMap = SensitiveWordInit.init(datas);
    }
    /**
     * 替换敏感字字符
     * @author chenming
     * @date 2014年4月20日 下午5:12:07
     * @param txt
     * @param matchType
     * @param replaceChar 替换字符,默认*
     * @version 1.0
     */
    public static String replaceSensitiveWord( String txt,int matchType,String replaceChar){
        if (sensitiveWordMap == null) {
            initSensitiveWord(datas);
        }
        String resultTxt = txt;
        List set = SensitiveWordInit.getSensitiveWord( txt, matchType ); //获取所有的敏感词
        System.out.println(set);
        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;
    }
    /**
     * 获取与词库中相匹配的词语
     * @author chenming
     * @date 2014年4月20日 下午5:12:07
     * @param txt
     * @param matchType
     * @param replaceChar 替换字符,默认*
     * @version 1.0
     */
    public static List getSensitiveWord(List datas, String txt,int matchType){
        if (sensitiveWordMap == null) {
            initSensitiveWord(datas);
        }
        List list = SensitiveWordInit.getSensitiveWord(txt, matchType); //获取所有的敏感词
        return list;
    }
    /**
     * 获取替换字符串
     * @author chenming
     * @date 2014年4月20日 下午5:21:19
     * @param replaceChar
     * @param length
     * @return
     * @version 1.0
     */
    private static String getReplaceChars(String replaceChar,int length){
        String resultReplace = replaceChar;
        if (length > 6) {
            length = 6;
        }
        for(int i = 1 ; i < length ; i++){
            resultReplace += replaceChar;
        }
        return resultReplace;
    }

    /**
     * 添加敏感词
     * @param str
     */
    private static boolean addSensitiveWord(String str) {
        if (sensitiveWordMap == null) {
            return false;
        }
        Map nowMap = null;
        Map newWorMap = null;
        nowMap = sensitiveWordMap;
        for(int i = 0 ; i < str.length() ; i++){
            char keyChar = str.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 == str.length() - 1){
                nowMap.put("isEnd", "1"); //最后一个
            }
        }
        return  true;
    }

}


2、敏感词过滤

package com.zhx.guides.assistant.util.file;

import org.apache.commons.lang.StringUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/****
 * *
 * 类名称:		StringWriteFile.java 
 * 类描述:   		字符保存到文件中
 * 创建人:		
 * 创建时间:		2016-10-10下午4:39:52 
 * 修改人:		liuxing
 * 修改时间:		2016-10-10下午4:39:52 
 * 修改备注:   		
 * @version
 */
public class StringWriteFile {
	
	/***
	 * 将信息写入到文件中,指定文件
	 * @param info
	 * @return
	 */
	public static boolean writerToFile( String info) {
		return writerTo( new File("D:/123.txt") , info );
	}
	
	/***
	 * 将信息写入到文件中
	 * @param file
	 * @param info
	 * @return
	 */
	public static boolean writerTo(File file, String info) {
		FileWriter fileWrite;
		try {
			fileWrite = new FileWriter(file , true ); 	// 新建一个FileWriter,并且配置成追加写入
			/*fileWrite.write(info); 				// 将字符串写入到指定的路径下的文件中
			fileWrite.close();*/
		} catch (IOException e) {
			return false;
		}
		PrintWriter printWriter = new PrintWriter( fileWrite ); 
		printWriter.println( info ); 
		printWriter.flush(); 
		try { 
			fileWrite.flush(); 
			printWriter.close(); 
			fileWrite.close(); 
		} catch (IOException e) { 
		e.printStackTrace(); 
		} 
		return true;
	}
	
	/***
	 * 将信息读出到List中
	 * @param file
	 * @return
	 */
	public static List readToListByFile( File file ){
		List urls = new ArrayList() ;
		String urlTempLine = null ;
		 try { // 防止文件建立或读取失败,用catch捕捉错误并打印,也可以throw  
            /* 读入TXT文件 */  
            InputStreamReader reader = new InputStreamReader( new FileInputStream(file)); // 建立一个输入流对象reader  
            BufferedReader br = new BufferedReader(reader); // 建立一个对象,它把文件内容转成计算机能读懂的语言  
            urlTempLine = br.readLine();  
            while (urlTempLine != null) {  
            	urlTempLine = br.readLine(); // 一次读入一行数据
				if(StringUtils.isNotBlank( urlTempLine ) && urlTempLine.length() > 45 ) {
					urls.add(urlTempLine.substring(0, 43));
				}
            }
		 }catch(Exception e) {
			 System.out.println( e.getMessage() );
		 }
		 return urls ;
	}


	/***
	 * 将信息读出到List中
	 * @param inputStream
	 * @return
	 */
	public static List readToList( InputStream inputStream ){
		List urls = new ArrayList() ;
		String urlTempLine = null ;
		try { // 防止文件建立或读取失败,用catch捕捉错误并打印,也可以throw
			/* 读入TXT文件 */
			InputStreamReader reader = new InputStreamReader( inputStream ); // 建立一个输入流对象reader
			BufferedReader br = new BufferedReader(reader); // 建立一个对象,它把文件内容转成计算机能读懂的语言
			urlTempLine = br.readLine();
			while (urlTempLine != null) {
				urlTempLine = br.readLine(); // 一次读入一行数据
				if(StringUtils.isNotBlank( urlTempLine ) ) {
					urls.add( urlTempLine );
				}
			}
		}catch(Exception e) {
			System.out.println( e.getMessage() );
		}
		return urls ;
	}


	/***
	 * 将信息读出到List中
	 * @param inputStream
	 * @return
	 */
	public static String readToString( InputStream inputStream ){
		StringBuilder info = new StringBuilder() ;
		String urlTempLine = null ;
		try { // 防止文件建立或读取失败,用catch捕捉错误并打印,也可以throw
			/* 读入TXT文件 */
			InputStreamReader reader = new InputStreamReader( inputStream ); // 建立一个输入流对象reader
			BufferedReader br = new BufferedReader(reader); // 建立一个对象,它把文件内容转成计算机能读懂的语言
			urlTempLine = br.readLine();
			while (urlTempLine != null) {
				urlTempLine = br.readLine(); // 一次读入一行数据
				if(StringUtils.isNotBlank( urlTempLine ) ) {
					info.append( urlTempLine );
				}
			}
		}catch(Exception e) {
			System.out.println( e.getMessage() );
		}
		return info.toString() ;
	}


	public static void main(String[] args) {

		List tempUrls = StringWriteFile.readToListByFile( new File("C://huixun.txt") ) ;
		StringWriteFile.writerTo(new File("D:/123.txt"), "test" ) ;
	}
	
}
package com.zhx.guides.collect.util.object.word;

import com.zhx.guides.collect.util.object.StringWriteFile;
import org.springframework.core.io.ClassPathResource;

import java.io.*;
import java.util.*;

/**
 * @Class SensitiveWordInit
 * @Author 作者姓名:
 * @Version 1.0
 * @Date 创建时间:2020-05-22 14:49
 * @Copyright Copyright by **** company
 * @Direction 类说明 初始化敏感词库,将敏感词加入到HashMap中,构建DFA算法模型
 */
public class SensitiveWordInit {

    private static String ENCODING = "UTF-8"; //字符编码

    @SuppressWarnings("rawtypes")
    public static HashMap sensitiveWordMap;

    public SensitiveWordInit(){
        super();
    }

    /**
     * 初始化词库
     * @param datas 敏感词集合
     * @return
     */
    public static HashMap init(List datas) {
        addSensitiveWord(datas);
        return sensitiveWordMap;
    }

    /**
     * 读取敏感词库,将敏感词放入HashSet中,构建一个DFA算法模型:
     * */
    private static void addSensitiveWord(List datas) {
        sensitiveWordMap = new HashMap(datas.size());
        Iterator iterator = datas.iterator();
        Map now = null;
        Map now2 = null;
        while (iterator.hasNext()) {
            now2 = sensitiveWordMap;
            String word = iterator.next().trim(); //敏感词
            for (int i = 0; i < word.length(); i++) {
                char key_word = word.charAt(i);
                Object obj = now2.get(key_word);
                if (obj != null) { //存在
                    now2 = (Map) obj;
                } else { //不存在
                    now = new HashMap();
                    now.put("isEnd","0");
                    now2.put(key_word, now);
                    now2 = now;
                }
                if (i == word.length() - 1) {
                    now2.put("isEnd","1");
                }
            }
        }
    }

    /**
     * 获取内容中的敏感词
     * @param text 内容
     * @param matchType 匹配规则 1=不最佳匹配,2=最佳匹配
     * @return
     */
    public static List getSensitiveWord(String text, int matchType) {
        List words = new ArrayList();
        Map now = sensitiveWordMap;
        int count = 0; //初始化敏感词长度
        int start = 0; //标志敏感词开始的下标
        for (int i = 0; i < text.length(); i++) {
            char key = text.charAt(i);
            now = (Map) now.get(key);
            if (now != null) { //存在
                count++;
                if (count ==1) {
                    start = i;
                }
                if ("1".equals(now.get("isEnd"))) { //敏感词结束
                    now = sensitiveWordMap; //重新获取敏感词库
                    words.add(text.substring(start, start + count)); //取出敏感词,添加到集合
                    count = 0; //初始化敏感词长度
                }
            } else { //不存在
                now = sensitiveWordMap;//重新获取敏感词库
                if (count == 1 && matchType == 1) { //不最佳匹配
                    count = 0;
                } else if (count == 1 && matchType == 2) { //最佳匹配
                    words.add(text.substring(start, start + count));
                    count = 0;
                }
            }
        }
        return words;
    }

    /**
     * 从springboot 配置文件中读取词库中的内容,将内容添加到list集合中
     * @author xing .liu
     * @date 2020年5月22日 下午2:31:18
     * @return
     * @version 1.0
     * @throws Exception
     */
    @SuppressWarnings("resource")
    public static List readSensitiveWordFile() throws Exception{
        ClassPathResource classPathResource = new ClassPathResource("SensitiveWord.txt");
        InputStream inputStream = classPathResource.getInputStream();
        return StringWriteFile.readToList(inputStream);
    }

    /****
     * 这个是直接调用指定路径
     * @author zhiju.li
     * @date 2019年4月12日 下午2:31:18
     * @return
     * @version 1.0
     * @throws Exception
     */
    public static List readSensitiveWordByFile() throws Exception{

    List list = null;
        //File file = new File("msc/SensitiveWord.txt"); //读取文件
        File file = new File("D:\\SensitiveWord.txt"); //读取文件
        InputStreamReader read = new InputStreamReader(new FileInputStream(file),ENCODING);
        try {
            if(file.isFile() && file.exists()){ //文件流是否存在
                list = new ArrayList();
                BufferedReader bufferedReader = new BufferedReader(read);
                String txt = null;
                while((txt = bufferedReader.readLine()) != null){ //读取文件,将文件内容放入到set中
                    String[] strSplit=txt.trim().split(",");
                    for(String str:strSplit){
                        list.add(str);
                    }
                }
            }else{ //不存在抛出异常信息
                throw new Exception("词库文件不存在");
            }
        } catch (Exception e) {
            throw e;
        }finally{
            read.close(); //关闭文件流
        }
        return list;
    }

}


3、敏感词库配置

Java 处理字符串中的敏感词 配置模式_第1张图片

SensitiveWord.txt

猪肉
羊肉
牛肉

4、测试方法

package com.zhx.guides.collect.util.object.word;

/**
 * @Class WordMainTest
 * @Author 作者姓名:****
 * @Version 1.0
 * @Date 创建时间:2020-05-22 14:52
 * @Copyright Copyright by ***company
 * @Direction 类说明
 */
public class WordMainTest {

    public static void main(String[] args) throws Exception {
        //输入的字符串
        String str = "你好,帮我查看下今天的 猪肉、牛肉、羊肉、 的价格状况信息";
        long l1 = System.currentTimeMillis() ;
        String response = SensitivewordFilter.replaceSensitiveWord( str,1,"*");
        long l2 = System.currentTimeMillis() ;
        response = SensitivewordFilter.replaceSensitiveWord( str,1,"*");
        long l3 = System.currentTimeMillis() ;
        logger.info("第一次需要加载配置文件耗时:{} ... {}" ,  (l2-l1) , response );
        logger.info("第二次纯内存计算耗时:{} ... {} " ,  (l3-l2) , response );
    }

}

看看运行结果:


[猪肉, 牛肉, 羊肉]
[猪肉, 牛肉, 羊肉]
23:08:55.380 [main] INFO com.zhx.guides.collect.util.object.word.WordMainTest - 第一次需要加载配置文件耗时:40 ... 你好,帮我查看下今天的 **、**、**、 的价格状况信息
23:08:55.387 [main] INFO com.zhx.guides.collect.util.object.word.WordMainTest - 第二次纯内存计算耗时:0 ... 你好,帮我查看下今天的 **、**、**、 的价格状况信息 

5、Springboot 如果打包jar找不到配置文件

pom.xml

  
    
        
                src/main/resources
                
                    **/*.yml
                    **/*.properties
                    **/*.xml
                    **/*.png
                    **/*.txt
                
                false
            
        



这个记得加上就行
**/*.txt

你可能感兴趣的:(分词器,java,字符串替换)