敏感词过滤工具类(DFA算法匹配字典)

本文介绍了一个使用DFA(确定有限状态自动机)算法实现的敏感词过滤工具类,通过调用特定方法wordFilter,可以高效地进行敏感词的检测和过滤。

直接调用方法:wordFilter

package com.util;


import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 敏感词处理 - DFA算法实现
 *
 * @author jeff
 * @since 2018/3/15
 */
public class SensitiveWordUtil {
   
   

    /**
     * 敏感词匹配规则
     */
    public static final int MinMatchTYpe = 1;      //最小匹配规则,如:敏感词库["中国","中国人"],语句:"我是中国人",匹配结果:我是[中国]人
    public static final int MaxMatchType = 2;      //最大匹配规则,如:敏感词库["中国","中国人"],语句:"我是中国人",匹配结果:我是[中国人]

    /**
     * 敏感词集合
     */
    public static HashMap sensitiveWordMap;

    /**
     * 初始化敏感词库,构建DFA算法模型
     *
     * @param sensitiveWordSet 敏感词库
     */
    public static synchronized void init(Set<String> sensitiveWordSet) {
   
   
        initSensitiveWordMap(sensitiveWordSet);
    }

    /**
     * 初始化敏感词库,构建DFA算法模型
     *
     * @param sensitiveWordSet 敏感词库
     */
    private static void initSensitiveWordMap(Set<String> sensitiveWordSet) {
   
   
        //初始化敏感词容器,减少扩容操作
        sensitiveWordMap = new HashMap(sensitiveWordSet.size());
        String key;
        Map nowMap;
        Map<String, String> newWorMap;
        //迭代sensitiveWordSet
        Iterator<String> iterator = sensitiveWordSet.iterator();
        while (iterator.hasNext()) {
   
   
            //关键字
            key = iterator.next();
            nowMap = sensitiveWordMap;
            for (int i = 0; i < key.length(); i++) {
   
   
                //转换成char型
                char keyChar = key.charAt(i);
                //库中获取关键字
                Object wordMap = nowMap.get(keyChar);
                //如果存在该key,直接赋值,用于下一个循环获取
                if (wordMap != null) {
   
   
                    nowMap = (Map) wordMap;
                } else {
   
   
                    //不存在则,则构建一个map,同时将isEnd设置为0,因为他不是最后一个
                    newWorMap = new HashMap<>();
                    //不是最后一个
### Java 中与 DFA 相关的工具类实现 在构建词法分析器或其他模式匹配应用时,DFA(确定有限状态自动机)是一个重要的概念。下面展示了一个简单的基于 DFA敏感词过滤工具类,在 Java 中实现了这一功能。 #### 敏感词过滤工具类定义 此部分展示了如何创建一个静态方法用于初始化敏感词库并加载字典文件: ```java import java.io.BufferedReader; import java.io.FileReader; import java.util.HashMap; import java.util.Map; public class DFASensitiveWordFilter { private static final Map<String, Integer> sensitiveWordsMap = new HashMap<>(); private static final int minMatchType = 1; // 最小匹配规则 private static final int maxMatchType = 2; // 最大匹配规则 /** * 初始化敏感词库 */ public static void init() { try (BufferedReader br = new BufferedReader(new FileReader("/usr/share/digital/files/dictionary.txt"))) { // 加载敏感词库 String lineTxt; while ((lineTxt = br.readLine()) != null) { addSensitiveWordToHashMap(lineTxt.trim()); } } catch (Exception e) { System.out.println(e.getMessage()); } } /** * 将单个敏感词添加至哈希表中 * * @param key 待处理字符串(敏感词) */ private static void addSensitiveWordToHashMap(String key) { StringBuilder tempKey = new StringBuilder(); for (int i = 0; i < key.length(); ++i) { char c = key.charAt(i); tempKey.append(c); if (!sensitiveWordsMap.containsKey(tempKey.toString())) { sensitiveWordsMap.put(tempKey.toString(), 1); // 这里的value可以设置成其他值表示不同的含义 } } } } ``` 上述代码片段通过读取指定路径下的 `dictionary.txt` 文件来填充敏感词列表,并将其存储在一个哈希映射结构内以便快速查找[^2]。 #### 使用 DFA 算法进行文本替换 接下来的部分提供了两个主要的方法:一个是用来检测给定文本中存在的敏感词汇;另一个则是执行实际的文字替换工作。 ```java /** * 替换传入的内容中的敏感词,*号代表敏感词 * * @param txt 文本原文 * @return 如果存在非法字符返回替换后的结果,否则返回原参数 */ public static String replaceSensitiveWord(String txt) { StringBuffer resultBuf = new StringBuffer(); String word = checkSensitiveWord(txt, minMatchType); if (word != null && !"".equals(word)) { resultBuf.append(getReplaceChar(word.length())); } else { resultBuf.append(txt); } return resultBuf.toString(); } /** * 获取替换*的数量,根据匹配的结果获得相应的* * * @param length 字符串长度 * @return 返回相应数量的* */ private static String getReplaceChar(int length) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < length; i++) { sb.append("*"); } return sb.toString(); } /** * 检查文字中是否包含敏感字符,检查规则如下:<br> * 从左向右扫描,当发现首字母符合某个敏感词开头,则取出该敏感词最大长度的子串与敏感词库对比, * 若不存在则去除最后一个字符继续比较直到仅剩下一个字符为止。<br> * 参数minMatchType 控制最小匹配原则<br> * 参数maxMatchType 控制最大匹配原则 * * @param txt 要判断的目标文本 * @param matchType 可选值为DFASensitiveWordFilter.minMatchType 或者 DFASensitiveWordFilter.maxMatchType * @return 如果存在非法字符返回第一个被识别出来的敏感词,否则返回null */ public static String checkSensitiveWord(String txt, int matchType) { boolean flag = false; // 是否存在敏感词,默认false int beginIndex = 0; // 开始位置索引 int endIndex = 0; // 结束位置索引 char[] chars = txt.toCharArray(); int length = chars.length; Map nowMap = sensitiveWordsMap; for (int i = 0; i < length; i++) { Character character = chars[i]; Object wordMap = nowMap.get(character); if (wordMap != null) { String key = nowMap.get("isEnd") == null ? "" : "isEnd"; if ("isEnd".equals(key)) { flag = true; endIndex = i + 1; break; } else { nowMap = (Map) wordMap; } } else { nowMap = sensitiveWordsMap; beginIndex++; i = beginIndex - 1; } } if (flag) { switch (matchType) { case minMatchType: return txt.substring(beginIndex, endIndex).toString(); default: return ""; } } return null; } ``` 这段程序逻辑上先尝试找到最短可能存在的敏感词实例,一旦成功即刻停止进一步搜索并立即返回所找到的第一个敏感词作为结果。对于更复杂的场景比如最长匹配需求也可以很容易调整以上函数的行为[^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值