1. 程式人生 > >Java 利用DFA算法 屏蔽敏感詞

Java 利用DFA算法 屏蔽敏感詞

www 操作 情況 author 敏感詞 while tex bsp hashset

原文:http://www.open-open.com/code/view/1435214601278

    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); } }

Java 利用DFA算法 屏蔽敏感詞