Java 利用DFA算法 屏蔽敏感词

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * 初始化敏感词库<br>
 * 将敏感词加入到HashMap中<br>
 * 构建DFA算法模型
 *
 * @author dxm
 *
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public class SensitiveWordInit {

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

	/**
	 * 初始化敏感字库
	 *
	 * @return
	 */
	public Map initKeyWord() {

		// 读取敏感词库
		Set<String> wordSet = readSensitiveWordFile();

		// 将敏感词库加入到HashMap中
		return addSensitiveWordToHashMap(wordSet);
	}

	/**
	 * 读取敏感词库,将敏感词放入HashSet中,构建一个DFA算法模型:<br>
	 * 中 = { isEnd = 0 国 = {<br>
	 * isEnd = 1 人 = {isEnd = 0 民 = {isEnd = 1} } 男 = { isEnd = 0 人 = { isEnd =
	 * 1 } } } } 五 = { isEnd = 0 星 = { isEnd = 0 红 = { isEnd = 0 旗 = { isEnd = 1
	 * } } } }
	 *
	 */
	private Map addSensitiveWordToHashMap(Set<String> wordSet) {

		// 初始化敏感词容器,减少扩容操作
		Map wordMap = new HashMap(wordSet.size());

		for (String word : wordSet) {
			Map nowMap = wordMap;
			for (int i = 0; i < word.length(); i++) {

				// 转换成char型
				char keyChar = word.charAt(i);

				// 获取
				Object tempMap = nowMap.get(keyChar);

				// 如果存在该key,直接赋值
				if (tempMap != null) {
					nowMap = (Map) tempMap;
				}

				// 不存在则,则构建一个map,同时将isEnd设置为0,因为他不是最后一个
				else {

					// 设置标志位
					Map<String, String> newMap = new HashMap<String, String>();
					newMap.put("isEnd", "0");

					// 添加到集合
					nowMap.put(keyChar, newMap);
					nowMap = newMap;
				}

				// 最后一个
				if (i == word.length() - 1) {
					nowMap.put("isEnd", "1");
				}
			}
		}

		return wordMap;
	}

	/**
	 * 读取敏感词库中的内容,将内容添加到set集合中
	 *
	 * @return
	 * @throws Exception
	 */
	private Set<String> readSensitiveWordFile() {

		Set<String> wordSet = null;

		// 读取文件
		String app = System.getProperty("user.dir");
		File file = new File(app + "/src/sensitive.txt");
		try {

			InputStreamReader read = new InputStreamReader(new FileInputStream(file), ENCODING);

			// 文件流是否存在
			if (file.isFile() && file.exists()) {

				wordSet = new HashSet<String>();
				StringBuffer sb = new StringBuffer();
				BufferedReader bufferedReader = new BufferedReader(read);
				String txt = null;

				// 读取文件,将文件内容放入到set中
				while ((txt = bufferedReader.readLine()) != null) {
					sb.append(txt);
				}
				bufferedReader.close();

				String str = sb.toString();
				String[] ss = str.split(",");
				for (String s : ss) {
					wordSet.add(s);
				}
			}

			// 关闭文件流
			read.close();

		} catch (Exception e) {
			e.printStackTrace();
		}

		return wordSet;
	}
}
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * 敏感词过滤
 *
 * @author dxm
 *
 */
@SuppressWarnings("rawtypes")
public class SensitivewordFilter {

	private Map sensitiveWordMap = null;

	// 最小匹配规则
	public static int minMatchTYpe = 1;

	// 最大匹配规则
	public static int maxMatchType = 2;

	// 单例
	private static SensitivewordFilter inst = null;

	/**
	 * 构造函数,初始化敏感词库
	 */
	private SensitivewordFilter() {
		sensitiveWordMap = new SensitiveWordInit().initKeyWord();
	}

	/**
	 * 获取单例
	 *
	 * @return
	 */
	public static SensitivewordFilter getInstance() {
		if (null == inst) {
			inst = new SensitivewordFilter();
		}
		return inst;
	}

	/**
	 * 判断文字是否包含敏感字符
	 *
	 * @param txt
	 * @param matchType
	 * @return
	 */
	public boolean isContaintSensitiveWord(String txt, int matchType) {
		boolean flag = false;
		for (int i = 0; i < txt.length(); i++) {

			// 判断是否包含敏感字符
			int matchFlag = this.CheckSensitiveWord(txt, i, matchType);

			// 大于0存在,返回true
			if (matchFlag > 0) {
				flag = true;
			}
		}
		return flag;
	}

	/**
	 * 获取文字中的敏感词
	 *
	 * @param txt
	 * @param matchType
	 * @return
	 */
	public Set<String> getSensitiveWord(String txt, int matchType) {
		Set<String> sensitiveWordList = new HashSet<String>();

		for (int i = 0; i < txt.length(); i++) {

			// 判断是否包含敏感字符
			int length = CheckSensitiveWord(txt, i, matchType);

			// 存在,加入list中
			if (length > 0) {
				sensitiveWordList.add(txt.substring(i, i + length));

				// 减1的原因,是因为for会自增
				i = i + length - 1;
			}
		}

		return sensitiveWordList;
	}

	/**
	 * 替换敏感字字符
	 *
	 * @param txt
	 * @param matchType
	 * @param replaceChar
	 * @return
	 */
	public String replaceSensitiveWord(String txt, int matchType, String replaceChar) {

		String resultTxt = txt;

		// 获取所有的敏感词
		Set<String> set = getSensitiveWord(txt, matchType);
		Iterator<String> 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 replaceChar
	 * @param length
	 * @return
	 */
	private String getReplaceChars(String replaceChar, int length) {
		String resultReplace = replaceChar;
		for (int i = 1; i < length; i++) {
			resultReplace += replaceChar;
		}

		return resultReplace;
	}

	/**
	 * 检查文字中是否包含敏感字符,检查规则如下:<br>
	 * 如果存在,则返回敏感词字符的长度,不存在返回0
	 *
	 * @param txt
	 * @param beginIndex
	 * @param matchType
	 * @return
	 */
	public int CheckSensitiveWord(String txt, int beginIndex, int matchType) {

		// 敏感词结束标识位:用于敏感词只有1位的情况
		boolean flag = false;

		// 匹配标识数默认为0
		int matchFlag = 0;
		Map nowMap = sensitiveWordMap;
		for (int i = beginIndex; i < txt.length(); i++) {
			char word = txt.charAt(i);

			// 获取指定key
			nowMap = (Map) nowMap.get(word);

			// 存在,则判断是否为最后一个
			if (nowMap != null) {

				// 找到相应key,匹配标识+1
				matchFlag++;

				// 如果为最后一个匹配规则,结束循环,返回匹配标识数
				if ("1".equals(nowMap.get("isEnd"))) {

					// 结束标志位为true
					flag = true;

					// 最小规则,直接返回,最大规则还需继续查找
					if (SensitivewordFilter.minMatchTYpe == matchType) {
						break;
					}
				}
			}

			// 不存在,直接返回
			else {
				break;
			}
		}

		// 长度必须大于等于1,为词
		if (matchFlag < 2 || !flag) {
			matchFlag = 0;
		}
		return matchFlag;
	}

	public static void main(String[] args) {

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");

		SensitivewordFilter filter = SensitivewordFilter.getInstance();
		String txt = "太多的伤感情怀也许只局限于饲养基地 荧幕中的情节,主人公尝试着去用某种方式渐渐的很潇洒地释自杀指南怀那些自己经历的伤感。" + "然后法轮功 我们的扮演的角色就是跟随着主人公的喜红客联盟 怒哀乐而过于牵强的把自己的情感也附加于银幕情节中,然后感动就流泪," + "难过就躺在某一个人的怀里尽情的阐述心扉或者手机卡复制器一个人一杯红酒一部电影在夜三级片 深人静的晚上,关上电话静静的发呆着。";
		txt = "法轮大法";
		System.out.println(sdf.format(new Date()));
		String hou = filter.replaceSensitiveWord(txt, 1, "*");
		System.out.println(sdf.format(new Date()));
		System.out.println("替换前的文字为:" + txt);
		System.out.println("替换后的文字为:" + hou);
	}
}

时间: 2024-08-02 16:44:48

Java 利用DFA算法 屏蔽敏感词的相关文章

DFA算法过滤敏感词整理

这里有部分是从网上找的,但看起来太乱了,分的太散了.研究了几天,整理出来,有问题的话还请大虾们提出来.... package org.rui.util; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashMap; i

基于DFA算法的敏感词过滤

DFA算法的全称是Deterministic Finite Automaton,即确定有穷永动机算法. DFA算法中对汉字的存储,字典树中的节点存储的字符Character类型,不是ASCII码. 建立默认敏感词替换词 private sttaic final String REPLACE=" whatever"; 定义字典树 字典树中的节点拥有以下属性: 1.kv键值对类型的子节点,key中保存着敏感词,v是triedNode类型的保存节点 2.代表分支结尾的end属性 3.给字典树

萌新笔记——用KMP算法与词典实现屏蔽敏感词(UTF-8编码)

前几天写好了字典,又刚好重温了KMP算法,恰逢遇到朋友吐槽最近被和谐的词越来越多了,于是突发奇想,想要自己实现一下敏感词屏蔽. 基本敏感词的屏蔽说起来很简单,只要把字符串中的敏感词替换成"***"就可以了.对于子串的查找,就KMP算法就可以了.但是敏感词这么多,总不能一个一个地遍历看看里面有没有相应的词吧! 于是我想到了前几天写的字典树.如果把它改造一下,并KMP算法结合,似乎可以节约不少时间. 首先说明一下思路: 对于KMP算法,这里不过多阐述.对于敏感词库,如果把它存进字典树,并在

java 实现DFA 算法(理论百度搜索)

DFA简介 DFA全称为:Deterministic Finite Automaton,即确定有穷自动机.(自己百度吧) 直接代码: 敏感词实体类 package com.nopsmile.dfa; public class Keywords { private String pid; private String Content; public Keywords() { } public Keywords(String content) { super(); Content = content

JS采用ActiveXObject实现用户在提交表单时屏蔽敏感词的功能

本例中敏感词ciku.txt放在C盘根目录下,采用的ActiveXObject插件获取本地文件内容.使用此插件不需网上下插件,直接用如下js代码即可. 浏览器需修改interner安全选项的级别,启用ActiveX才能获取到代码中的ActiveXObject插件.如下图所示: js代码实现如下: 1 <script type="text/javascript"> 2 // -------------- 全局变量,用来判断文本域中是否包含脏词,默认为false,即不包含脏词-

敏感词过滤

敏感词过滤是很多网站.论坛常用的功能,一下为相关文章: 1.关于java中敏感词检测的一些总结 2.Java 利用DFA算法 屏蔽敏感词 3.Java实现敏感词过滤--DFA算法

敏感词过滤的算法原理之DFA算法

参考文档 http://blog.csdn.net/chenssy/article/details/26961957 敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来一看,整个过程如下:读取敏感词库.如果HashSet集合中,获取页面上传文字,然后进行匹配.我就想这个过程肯定是非常慢的.对于他这个没有接触的人来说我想也只能想到这个,更高级点就是正

转:Java实现敏感词过滤

敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来一看,整个过程如下:读取敏感词库.如果HashSet集合中,获取页面上传文字,然后进行匹配.我就想这个过程肯定是非常慢的.对于他这个没有接触的人来说我想也只能想到这个,更高级点就是正则表达式.但是非常遗憾,这两种方法都是不可行的.当然,在我意识里没有我也没有认知到那个算法可以解决问题,但是Googl

Java实现敏感词过滤

敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来一看,整个过程如下:读取敏感词库.如果HashSet集合中,获取页面上传文字,然后进行匹配.我就想这个过程肯定是非常慢的.对于他这个没有接触的人来说我想也只能想到这个,更高级点就是正则表达式.但是非常遗憾,这两种方法都是不可行的.当然,在我意识里没有我也没有认知到那个算法可以解决问题,但是Googl