cenzurowanie słów składających się zkilku wyrazów

0

Cześć,
Robię aplikację GUI (podobną do notatnika), która na bieżąco sprawdza czy użytkownik nie wprowadził żadnych necenzuralnych słów i je ewentualnie gwiazdkuje (kurka => k***a). Nie mam problemu z jednoelementowymi wyrazami, ale muszę też wziąć pod uwagę całe wyrażenia. Załóżmy że badWordList to moja lista brzydkich słów i wyrażeń, a text to mój String z aktualnym tekstem wprowadzonym przez użytkownika. Do teraz sprawdzam to w ten sposób:

text=text.replaceAll("\\b"+badWordList.get(i)+"[?!.,:\\s]", replacement+text.charAt(text.length()-1));

Jednak jeśli mój badWordList będzie zawierał takie słowa jak "kurka" i "kurka wodna" to niestety wygwiazdkowana zostanie tylko "kurka" a "wodna" już nie. Jeśli miałabym tylko "kurka wodna" w mojej liście brzydkich słów, to wyrażenie zostanie wygwiazdkowane prawidłowo.

Wiem dlaczego tak się dzieje (od razu po wpisaniu "kurka" wywoływane jest zdarzenie przycisku i program znajduje już to w słowniku) ale nie wiem jak sobie z tym poradzić taż żeby czekał na "wodna"... biorąc pod uwagę, że muszę uważać na suffixy i prefixy (np. podsłuchuj już nie gwiazdkuję).

private Vector<String> badWordList=new Vector<String>();
   
    public MainJFrame() {
        initComponents();
        getBadWords();
        textArea.addKeyListener(new KeyAdapter() {

            @Override
            public void keyReleased(KeyEvent e) {
                textArea.setText(checkContents());
           }

            @Override
            public void keyTyped(KeyEvent e) {
               
            }

            @Override
            public void keyPressed(KeyEvent e) {           
            }
        });            
    }

    private String checkContents()
    {
        String text=textArea.getText();
      
        for(int i=0;i<badWordList.size();i++)
        {
            String replacement="";
            int size=badWordList.get(i).length();
            replacement+=badWordList.get(i).charAt(0);

            for(int j=0;j<size-2;j++)
            {
                replacement+="*";
            }

            replacement+=badWordList.get(i).charAt(size-1);
            text=text.replaceAll("\\b"+badWordList.get(i)+"[?!.,:\\s]", replacement+text.charAt(text.length()-1));
        }
        
        return text;       
    }

0

Proponuję trzymać w pamięci cały tekst do tej pory wpisany, i on text change zrobić update tego w pamięci, przeanalizować go względem słownika zaczynając od najdłuższych wyrażeń, kończąc na najkrótszych i wyświetlić przeanalizowaną wersję.

0

dobry pomysł, dzięki:)

0

Wszytko działa pięknie, tylko mam następny problem. Program sprawdza poprawność wyrazu przed wstawieniem znaków: !?: spacja itd. Ja natomiast chciałabym, żeby robił to po wstawieniu jednego z tych znaków.

Problem polega na tym, że nie mogę wstawić sekwencji

text=text.replaceAll("\\b"+badWordList.get(i)+"[?!.,:\\s]", replacement);

gdyż program mi utnie znaki przestankowe.

Natomiast to co było wcześniej, czyli

text=text.replaceAll("\\b"+badWordList.get(i)+"[?!.,:\\s]", replacement+text.charAt(text.length()-1));

tym bardziej nie zadziała, bo w ogóle psuje mi się wyświetlanie znaków w JTextArea.
Byłabym bardzo wdzięczna za pomoc.

To co do tej pory napisałam:

public class MainJFrame extends javax.swing.JFrame {

    private Vector<String> badWordList=new Vector<String>();
    private String wholeText="";

    public MainJFrame() {
        initComponents();
        getBadWords();
        textArea.addKeyListener(new KeyAdapter() {

            @Override
            public void keyReleased(KeyEvent e) {

             if(e.getKeyCode()==KeyEvent.VK_BACK_SPACE || e.getKeyCode()==KeyEvent.VK_DELETE)
             {
                wholeText=wholeText.substring(0,textArea.getText().length());
             }
             textArea.setText(checkContents());
                             
            }

            @Override
            public void keyTyped(KeyEvent e) {
                     wholeText+=e.getKeyChar();
                     System.out.println("wholeText: "+wholeText);               
            }

            @Override
            public void keyPressed(KeyEvent e) {
               
            }
        });
    }

    private String checkContents()
    {
        String text=wholeText;
        for(int i=0;i<badWordList.size();i++)
        {
            String replacement="";
            int size=badWordList.get(i).length();
            replacement+=badWordList.get(i).charAt(0);

            for(int j=0;j<size-2;j++)
            {
                replacement+="*";
            }

            replacement+=badWordList.get(i).charAt(size-1);
            text=text.replaceAll("\\b"+badWordList.get(i)+"\\b", replacement);
        }
        System.out.println("Zamieniony text:"+text);
        return text;
    }

    private void getBadWords()
    {
        FileReader fr = null;
        Vector<String> threeElements=new Vector<String>();
        Vector<String> twoElements=new Vector<String>();
        Vector<String> oneElement=new Vector<String>();
        try
        {
            String line = "";
            fr = new FileReader("wulgaryzmy.txt");
            BufferedReader bfr = new BufferedReader(fr);
            while ((line = bfr.readLine()) != null)
            {
                byte howManyWords=(byte)line.split(" ").length;
                if(howManyWords > 3 || howManyWords < 1)
                    continue;
                else if(howManyWords == 3)
                    threeElements.add(line);
                else if(howManyWords == 2)
                    twoElements.add(line);
                else
                    oneElement.add(line);
            }

           badWordList.addAll(threeElements);
           badWordList.addAll(twoElements);
           badWordList.addAll(oneElement);
        }
        catch (IOException ex)
        {
            Logger.getLogger(MainJFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
        finally
        {
            try
            {
                fr.close();
            }
            catch (IOException ex)
            {
                Logger.getLogger(MainJFrame.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

.....
}
0

z javy to ja potwornie rzadko korzystam/korzystałem więc nie wiem jak z kodem, ale koncept uniwersalny:

int index = -1;
while((index = text.IndexOf("\b"+badWordList.get(i)+"[?!.,:\s]")) > -1)
{
// tutaj zamieniamy badWordList.get(i) no co tylko tam chcesz :)
// wiemy gdzie się zaczyna - index i jaki jest długi - Length
// wycinamy od index, length znaków, wklejamy swoje i to tyle
}

0

Dzięki za odpowiedź, pomogło:) Tylko, że zamiast metody .indexOf() (która jako argument nie przyjmuje wyrażenia regularnego) trzeba było skorzystać z klasy Pattern i Matchers.
Pozdrawiam!

0

Hmm a może coś w tej konwencji:
<core=java>
package forum.note.model;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class BadWordLibary {
private final static Set<String> words = new HashSet<String>();
private final static Set<BadWordChain> expressions = new HashSet<BadWordChain>();
static {
// b.brzydkie :P
words.add("kurna");
words.add("cholera");
words.add("kurde");
}

static {
	expressions.add(new BadWordChain("kurka", "wodna"));
	expressions.add(new BadWordChain("kurna", "mać"));
	expressions.add(new BadWordChain("spadaj", "na", "drzewo"));
}

public boolean isBadWord(final String word) {
	if (word != null) {
		return words.contains(word.toLowerCase());
	}
	return false;
}

public boolean isWordInChain(final Object word) {
	if (word != null) {
		for (final BadWordChain chain : expressions) {
			if (chain.containsWord(word.toString())) {
				return true;
			}
		}
	}
	return false;
}

@SuppressWarnings("unchecked")
public boolean possibleBadWordChain(final Collection words) {
	if (words != null) {
		for (final BadWordChain chain : expressions) {
			if (chain.containsChain(words)) {
				return true;
			}
		}
	}
	return false;
}

@SuppressWarnings("unchecked")
public boolean isBadWordChain(final Collection words) {
	if (words != null) {
		for (final BadWordChain chain : expressions) {
			if (chain.matchesChain(words)) {
				return true;
			}
		}
	}
	return false;
}

/**
 * Ciąg brzydkich wyrażeń.
 */
private static class BadWordChain {
	private final List<String> chain;
	
	/**
	 * Kontruktor.
	 * 
	 * @param words ciąg słów
	 */
	private BadWordChain(final String...words) {
		this.chain = Arrays.asList(words);
	}
	
	boolean containsWord(final String word) {
		if (word != null) {
			return this.chain.contains(word.toLowerCase());
		}
		return false;
	}
	
	boolean containsChain(final Collection<Object> words) {
		if (words == null || words.size() > this.chain.size()) {
			return false;
		}
		int i = 0;
		for (final Object o : words) {
			if (!this.chain.get(i).equalsIgnoreCase(o.toString())) {
				return false;
			}
			i ++;
		}
		return true;
	}
	
	boolean matchesChain(final Collection<Object> words) {
		if (words == null || words.size() != this.chain.size()) {
			return false;
		}
		int i = 0;
		for (final Object o : words) {
			if (!this.chain.get(i).equalsIgnoreCase(o.toString())) {
				return false;
			}
			i ++;
		}
		return true;
	}
}

}


```java
package forum.note.text;

import forum.note.model.BadWordLibary;


class CensorableTextChunk {
	private final static char CENSOR_CHARACTER = '*';
	
	private StringBuilder buffer = new StringBuilder();
	private final TextType type;
	private boolean isCensored = false;
	
	public enum TextType {
		WORD,
		WHITESPACES
	};
	
	/**
	 * Konstruktor.
	 * 
	 * @param t
	 */
	CensorableTextChunk(final TextType t) {
		this.type = t;
	}
	
	public void append(final char c) {
		this.buffer.append(c);
	}
	
	public boolean isBadWord(final BadWordLibary libary) {
		if (this.isWord()) {
			return libary.isBadWord(buffer.toString());
		}
		return false;
	}
	
	public void setCensored(final boolean censored) {
		this.isCensored = censored;
	}
	
	public boolean isCensored() {
		return this.isCensored;
	}
	
	public boolean isWord() {
		return TextType.WORD.equals(this.type);
	}

	private String getCensoredText() {
		final String censoredText;
		if (this.getLength() <= 3) {
			censoredText = this.getCharSequence(CENSOR_CHARACTER, this.getLength());
		} else {
			final int length = this.getLength();
			censoredText = this.buffer.charAt(0) + 
				this.getCharSequence(CENSOR_CHARACTER, length - 2) + 
				this.buffer.charAt(length - 1);
		}
		return censoredText;
	}
	
	int getLength() {
		return buffer.length();
	}
	
	private String getCharSequence(final char c, final int size) {
		final StringBuilder sb = new StringBuilder(size);
		for (int i = 0; i < size; i++) {
			sb.append(c);
		}
		return sb.toString();
	}
	
	@Override
	public String toString() {
		if (this.isCensored()) {
			return this.getCensoredText();
		}
		return buffer.toString();
	}
}
package forum.note.text;

import java.util.LinkedList;
import java.util.List;

import forum.note.model.BadWordLibary;
import forum.note.text.CensorableTextChunk.TextType;

public class CensorableText {
	private final List<CensorableTextChunk> textSequence = new LinkedList<CensorableTextChunk>();
	
	private final BadWordLibary libary = new BadWordLibary();
	private final char[] text;
	private final char[] censoredText;
	
	/**
	 * Kontruktor.
	 * 
	 * @param chars tekst
	 */
	public CensorableText(final char[] chars) {
		this.text = chars;
		this.censoredText = this.createCensoredText();
	}
	
	/**
	 * Kontruktor.
	 * 
	 * @param s tekst
	 */
	public CensorableText(final String s) {
		this(s.toCharArray());
	}
	
	private char[] createCensoredText() {
		if (this.text == null) {
			return null;
		}
		final StringBuilder sb = new StringBuilder(this.text.length);
		this.parseText();
		
		this.censoreChains(this.textSequence);
		this.censoreWords(this.textSequence);
		this.append(sb, this.textSequence);
		
		final char[] result = new char[this.text.length];
		sb.getChars(0, sb.length(), result, 0);
		return sb.toString().toCharArray();
	}
	
	private void parseText() {
		this.textSequence.clear();
		CensorableTextChunk word = new CensorableTextChunk(TextType.WORD);
		CensorableTextChunk whitespace = new CensorableTextChunk(TextType.WHITESPACES);
		for (final char c : this.text) {
			if (Character.isLetter(c)) {
				if (whitespace.getLength() > 0) {
					this.textSequence.add(whitespace);
					whitespace = new CensorableTextChunk(TextType.WHITESPACES);
				}
				word.append(c);
			} else {
				if (word.getLength() > 0) {
					this.textSequence.add(word);
					word = new CensorableTextChunk(TextType.WORD);
				}
				whitespace.append(c);
			}
		}
		if (word.getLength() > 0) {
			this.textSequence.add(word);
		}
		if (whitespace.getLength() > 0) {
			this.textSequence.add(whitespace);
		}
	}
	
	protected void censoreChains(final List<CensorableTextChunk> text) {
		final List<CensorableTextChunk> chain = new LinkedList<CensorableTextChunk>();
		for (final CensorableTextChunk chunk : text) {
			this.checkChain(chain);
			if (chunk.isWord() && this.libary.isWordInChain(chunk)) {
				chain.add(chunk);
			}
		}
		chain.clear();
	}
	
	private void checkChain(final List<CensorableTextChunk> chain) {
		if (chain.size() > 0) {
			if (libary.isBadWordChain(chain)) {
				for (final CensorableTextChunk chunk : chain) {
					chunk.setCensored(true);
				}
				chain.clear();
			} else if (!libary.possibleBadWordChain(chain)){
				chain.clear();
			}
		}
	}
	
	protected void censoreWords(final List<CensorableTextChunk> text) {
		for (final CensorableTextChunk chunk : text) {
			if (chunk.isBadWord(this.libary)) {
				chunk.setCensored(true);
			}
		}
	}
	
	protected void append(final StringBuilder buffer, 
			final List<CensorableTextChunk> text) {
		for (final CensorableTextChunk chunk : text) {
			buffer.append(chunk);
		}
	}
	
	public char[] getCensoredChars() {
		return this.censoredText;
	}
	
	public String getCensoredText() {
		return new String(this.censoredText);
	}
	
	@Override
	public String toString() {
		return new String(this.text);
	}
	
}
package forum.note.text;

import javax.swing.text.BadLocationException;
import javax.swing.text.GapContent;
import javax.swing.text.Segment;

class CensoredGapContent extends GapContent {
	private static final long serialVersionUID = -2643330287968357188L;

	@Override
	public void getChars(final int where, final int len, final Segment segment)
			throws BadLocationException {
		final int end = where + len;
		this.checkLocation(where, end);
		final int gapStart = this.getGapStart();
		final int gapEnd = this.getGapEnd();
		
		final char[] censoredText = this.getCensoredText();
		
		if ((where + len) <= gapStart) {
		    // below gap
		    segment.array = censoredText;
		    segment.offset = where;
		} else if (where >= gapStart) {
		    // above gap
		    segment.array = censoredText;
		    segment.offset = gapEnd + where - gapStart;
		} else {
		    // spans the gap
		    int before = gapStart - where;
		    if (segment.isPartialReturn()) {
				segment.array = censoredText;
				segment.offset = where;
				segment.count = before;
				return;
		    }
		    // partial return not allowed, must copy
		    segment.array = new char[len];
		    segment.offset = 0;
		    System.arraycopy(censoredText, where, segment.array, 0, before);
		    System.arraycopy(censoredText, gapEnd, segment.array, before, len - before);
		}
		segment.count = len;
	}
	
	private void checkLocation(final int where, final int end) throws BadLocationException {
		if (where < 0 || end < 0) {
		    throw new BadLocationException("Invalid location", -1);
		}
		if (end > length() || where > length()) {
		    throw new BadLocationException("Invalid location", length() + 1);
		}
	}
	
	private char[] getCensoredText() {
		final CensorableText text = new CensorableText((char[]) this.getArray());
		return text.getCensoredChars();
	}
}
package forum.note.text;

import javax.swing.text.PlainDocument;

public class CensoredDocument extends PlainDocument {
	private static final long serialVersionUID = 2615069452316401682L;

	/**
	 * Konstruktor.
	 */
	public CensoredDocument() {
		super(new CensoredGapContent());
	}
}

Wówczas podpina się to tak:

JTextArea area = new JTextArea();
area.setDocument(new CensoredDocument());

1 użytkowników online, w tym zalogowanych: 0, gości: 1