Find multiple words in a String and get index of - java

I have a big String (XML Style) and I provide a text-field for capturing the words to search. All words found should be highlighted.
The problem i have is, that the words can appear multiple times in that String but only the first/or last word is highlighted.
I found out that the problem is that the selectionStart and ending is always the same.
Can u help me ?
public static void searchTextToFind(String textToFind) {
highlighter.removeAllHighlights();
String CurrentText = textPane.getText();
StringReader readtext;
BufferedReader readBuffer;
int i = 0;
int matches = 0;
readtext = new StringReader(CurrentText);
readBuffer = new BufferedReader(readtext);
String line;
try {
i = CurrentText.indexOf(textToFind);
int start = 0;
int end = 0;
Pattern p = Pattern.compile(textToFind);
while ((line = readBuffer.readLine()) != null) {
Matcher m = p.matcher(line);
// indicate all matches on the line
while (m.find()) {
matches++;
while (i >= 0) {
textPane.setSelectionStart(i);
textPane.setSelectionEnd(i + textToFind.length());
i = CurrentText.indexOf(textToFind, i + 1);
start = textPane.getSelectionStart();
end = textPane.getSelectionEnd();
try {
highlighter.addHighlight(start, end,
myHighlightPainter);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
}
}
} catch (IOException e1) {
e1.printStackTrace();
}
JOptionPane.showMessageDialog(paneXML,
matches+" matches have been found", "Matched",
JOptionPane.INFORMATION_MESSAGE);
}

You have a LOT of redundant code. Here's a short and sweet solution using String.indexOf
public static void searchTextToFind(String textToFind) {
highlighter.removeAllHighlights();
textToFind = textToFind.toLowerCase(); //STRINGS ARE IMMUTABLE OBJECTS
String currentText = textPane.getText(); //UPPERCASE LOCALS ARE EVIL
currentText = currentText.toLowerCase(); //STRINGS ARE IMMUTABLE OBJECTS
int offset = 0;
for(int index = currentText.indexOf(textToFind, offset); index >= 0; index = currentText.indexOf(textToFind, offset)){
int startIndex = currentText.indexOf(textToFind, offset);
int endIndex = startIndex + textToFind.length() - 1; //this gets you the inclusive endIndex.
textPane.setSelectionStart(startIndex);
textPane.setSelectionEnd(endIndex);
offset = startIndex + 1; //begin the NEXT search at startIndex + 1 so we don't match the same string over and over again
System.out.println(startIndex);
System.out.println(endIndex);
try {
highlighter
.addHighlight(startIndex, endIndex, myHighlightPainter);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
}

Related

Highlight specific text in JTextArea - Java

I'm trying to quickly highlight my specific text in JTextArea. The code I need is running too slow, and I would like to know if there is a faster way to highlight text without crashing the whole application.
I have over 5000 words to scroll through and see if there is a need to highlight them or not, but this code doesn't work great for me. I'm looking for a better way to do it. This is my code:
class MyHighlightPainter extends DefaultHighlighter.DefaultHighlightPainter
{
public MyHighlightPainter(Color color) {
super(color);
}
}
Highlighter.HighlightPainter myHighlightPainter = new MyHighlightPainter(Color.yellow);
public void Highligh(JTextComponent textComp, String pattern)
{
try {
Highlighter hilite = textComp.getHighlighter();
Document doc = textComp.getDocument();
String text = doc.getText(0, doc.getLength());
for(int pos = 0; (pos=text.toUpperCase().indexOf(pattern.toUpperCase(),pos))>=0; pos += pattern.length())
hilite.addHighlight(pos, pos+pattern.length(), myHighlightPainter);
} catch (Exception e) {}
}
public void keyReleased(KeyEvent arg0) {
String text = vocabolario.getText();
String[] parziale = new String[5000];
try {
String p1 = "SELECT definizione FROM Cherubini WHERE definizione LIKE '%", p2 = "%';", px = vocabolario.getText(), query = p1+px+p2;
ResultSet rs = Main.conn().createStatement().executeQuery(query);
while(rs.next())
{
String[] dati = { rs.getString("definizione") };
for(int i = 0; i < dati.length; i++) { parziale[i] = dati[i]; textArea.append(parziale[i]+"\n"); }
}
}
catch(SQLException exc) {}
Highligh(textArea,vocabolario.getText());
}
});
for(int pos = 0; (pos=text.toUpperCase().indexOf(pattern.toUpperCase(),pos))>=0; pos += pattern.length())
Why do you keep converting the data to upper case? This should only be done once:
String upperText = text.toUpperCase();
String upperPattern = pattern.toUpperCase();
for(int pos = 0; (pos = upperText.indexOf(upperPattern, pos)) >= 0; pos += pattern.length())

How can I get the line number where the word has been found?

private static List<A> compute(Path textFile, String word) {
List<A> results = new ArrayList<A>();
try {
Files.lines(textFile).forEach(line -> {
BreakIterator it = BreakIterator.getWordInstance();
it.setText(line.toString());
int start = it.first();
int end = it.next();
while (end != BreakIterator.DONE) {
String currentWord = line.toString().substring(start, end);
if (Character.isLetterOrDigit(currentWord.charAt(0))) {
if (currentWord.equals(word)) {
results.add(new WordLocation(textFile, line));
break;
}
}
start = end;
end = it.next();
}
});
} catch (IOException e) {
e.printStackTrace();
}
return results;
}
How can I get the line number which the word has been found?
I want to use a stream to calculate in Lamdba.
Do you have any idea?
public class Try {
public static void main(String[] args) {
Path path = Paths.get("etc/demo.txt");
List<String> result = compute(path, "Test");
result.stream().forEach(s -> System.out.println(s));
}
private static List<String> compute(Path textFilePath, String wordToFind) {
List<String> results = new ArrayList<String>();
// Added position and initialized with 0
int[] position = new int[]{0};
try {
Files.lines(textFilePath).forEach(line -> {
BreakIterator it = BreakIterator.getWordInstance();
it.setText(line.toString());
int start = it.first();
int end = it.next();
// Increment position by 1 for each line
position[0] += 1;
while (end != BreakIterator.DONE) {
String currentWord = line.toString().substring(start, end);
if (Character.isLetterOrDigit(currentWord.charAt(0))) {
if (currentWord.equals(wordToFind)) {
results.add("File Path: " + textFilePath + ", Found Word: " + wordToFind + ", Line: " + position[0]);
break;
}
}
start = end;
end = it.next();
}
});
} catch (IOException e) {
e.printStackTrace();
}
return results;
}
}
demo.txt:
Stream1
Review
Stream
2020-10-10 10:00
Test
0.0
admin HOST Test
Stream2
Review
Output:
Note:
This is an example for your reference as it uses List<String>.
Added int[] position = new int[]{0}; and position[0] += 1; for line numbers to be displayed.
In above example Test exists in line number 5 and 7.
You can use a LineNumberReader to get the linenumber. That would look something like this:
private static List<A> compute(Path textFile, String word) {
List<A> results = new ArrayList<A>();
try (final LineNumberReader reader = new LineNumberReader(new FileReader(textFile.toFile()))) {
String line;
while ((line = reader.readLine()) != null) {
BreakIterator it = BreakIterator.getWordInstance();
it.setText(line);
int start = it.first();
int end = it.next();
final int lineNumber = reader.getLineNumber(); // here is your linenumber
while (end != BreakIterator.DONE) {
String currentWord = line.substring(start, end);
if (Character.isLetterOrDigit(currentWord.charAt(0))) {
if (currentWord.equals(word)) {
results.add(new WordLocation(textFile, line));
break;
}
}
start = end;
end = it.next();
}
}
} catch (IOException e) {
e.printStackTrace();
}
return results;
}

How to get line number in file from the character position using java

I have one JSON file and having some issue in it. When parsing the json file I will get the ParserException. From parser exception I have extracted the position where the is problem.
Now I want the line number of the that particular position in file.
JSONObject json;
try {
if (!file.exists()) {
throw new ExceptionDoesNotExist(file);
}
scanner = new Scanner(file, Charset.defaultCharset().toString());
String data = scanner.useDelimiter("\\Z").next();
json = (JSONObject) new JSONParser().parse(data);
return json;
} catch (ParseException e) {
this.log.logException(e);
int position = e.getPosition();
String reason = e.getUnexpectedObject().toString();
return new JSONObject();
}
if (!file.exists()) {
throw new ExceptionDoesNotExist(file);
}
scanner = new Scanner(file, Charset.defaultCharset().toString());
String data = scanner.useDelimiter("\\Z").next();
try {
return new JSONParser().parse(data);
} catch (ParseException e) {
String lineAndColumn = lineAndColumn(data, e, 4);
...;
return new JSONObject();
}
public static String lineAndColumn(String text, ParseException e, int tabSize) {
int position = e.getPosition();
int lineNo = 1 + (int) text.substring(0, position).codePoints()
.filter(cp -> cp == '\n')
.count();
int columnNo = 1 + text.substring(0, position).lastIndexOf('\n') + 1; // no \n okay too.
// Tabs
int cI = 0;
for (int i = 0; i < columnNo - 1; ++i) {
if (text.charAt(posion - (columnNo - 1) + i) == '\t') {
cI += tabSize;
cI %= tabSize;
} else {
++cI;
}
}
columnNo = cI + 1;
return String.format("%d:%d"), lineNo, ColumnNo);
}

J2ME , Quizz using choiceGroups

I am working on a driving licence project on j2Me wich is including Tests like quizz , well and i am having a problem after parsing the questions and moving them into choiceGroups just like that :
if (questions.length > 0) {
for (int i = 0; i < questions.length; i++) {
ChoiceGroup reponses = new ChoiceGroup("Reponses" + i, Choice.EXCLUSIVE);
reponses.append(questions[i].getReponse1(), null);
reponses.append(questions[i].getReponse2(), null);
reponses.append(questions[i].getReponse3(), null);
pass.append(questions[i].getContenu());
pass.append(reponses);
}
}
} catch (Exception e) {
System.out.println("Exception:" + e.toString());
}
disp.setCurrent(pass);
and the next step is the command who's controlling the choiceGroups to test them if they are like the true answer or not .
so i am blocked here .
if (c == valider) {
int result = 0;
for (int i = 0; i < pass.size(); i++) {
String ch = pass.get(i).getLabel();
System.out.println(ch);
}
}
I don't know how to get the choice from the choicegroup
any help
Actually, I am not sure what totally you want for:
This code will help you get selected items from choicegroup that i did long time before:
//get a selected array in choicegroup
private String[] choiceGroupSelected(ChoiceGroup cg) {
String selectedArray[] = new String[cg.size()];
int k = 0;
for (int i = 0; i < cg.size(); i++) {
if (cg.isSelected(i)) {
selectedArray[k] = cg.getString(i);
k++;
}
}
return selectedArray;
}
That function will help me get all selected items for deleting action below:
private void deleteSpecificItem() {
try {
String temp = null;
int index;
//get ChoiceGroup size
int numbers = cgTrip.size();
String selectedItems[] = choiceGroupSelected(cgTrip);
//
rs = services.RecordStoreManager.openRecordStoreByName("TripRS");
re = rs.enumerateRecords(null, null, true);
String[] tripList = new String[2];
for (int i = 0; i < numbers; i++) {
temp = selectedItems[i];
if (temp != null) {
while (re.hasNextElement()) {
try {
index = re.nextRecordId();
System.out.println("RecordID: " + index);
byte[] byteBuff = rs.getRecord(index);
String source = new String(byteBuff);
tripList = services.StringManager.getItems(source, ";", 2);
String strProcess = tripList[0] + "-" + tripList[1];
//inspect all of items in choicegroup and if they are selecting then compare with record
//If comparison is true then delete this record
if (temp.equals(strProcess)) {
System.out.println("Delete RecordID: " + index);
rs.deleteRecord(index);
re.keepUpdated(true);
break;
}
} catch (RecordStoreException ex) {
ex.printStackTrace();
}
}
}
}
try {
rs.closeRecordStore();
} catch (RecordStoreException ex) {
ex.printStackTrace();
}
rs = null;
re.destroy();
this.LoadTripItem();
} catch (RecordStoreNotOpenException ex) {
ex.printStackTrace();
}
}

First line and last line in jtextarea viewport

i am looking for a function which gives the viewport starting line and viewport ending line from jtextarea. The below code works fine. But when the number of lines in the jtextarea is too big, say 10,000 lines, response of the cursor becoming very slow. I narrowed down the line which is causing it, it is,
startLine = getRow(topLeft, editorTextArea) - 1; //editorTextArea is jtextarea name
endLine = getRow(bottomRight, editorTextArea);
I am calling the startAndEndLine() on every keyPressEvent
Can someone suggest me a better code, which is efficient?
private void startAndEndLine() {
Rectangle r = editorTextArea.getVisibleRect();
Point topLeft = new Point(r.x, r.y);
Point bottomRight = new Point(r.x + r.width, r.y + r.height);
try {
startLine = getRow(topLeft, editorTextArea) - 1;
endLine = getRow(bottomRight, editorTextArea);
} catch (Exception ex) {
// System.out.println(ex);
}
}
public int getViewToModelPos(Point p, JTextComponent editor) {
int pos = 0;
try {
pos = editor.viewToModel(p);
} catch (Exception ex) {
}
return pos;
}
public int getRow(Point point, JTextComponent editor) {
int pos = getViewToModelPos(point, editor);
int rn = (pos == 0) ? 1 : 0;
try {
int offs = pos;
while (offs > 0) {
offs = Utilities.getRowStart(editor, offs) - 1;
rn++;
}
} catch (BadLocationException e) {
System.out.println(e);
}
return rn;
}
This is based on a solution by JigarJoshi from this question Java: column number and line number of cursor's current position ... You gotta love this site ;)
protected int getLineNumber(int modelPos) throws BadLocationException {
return textArea.getLineOfOffset(modelPos) + 1;
}
Rectangle viewRect = scrollPane.getViewport().getViewRect();
Point startPoint = viewRect.getLocation();
int pos = textArea.viewToModel(startPoint);
try {
int startLine = getLineNumber(pos);
Point endPoint = startPoint;
endPoint.y += viewRect.height;
pos = textArea.viewToModel(endPoint);
int endLine = getLineNumber(pos);
System.out.println(startLine + " - " + endLine);
} catch (BadLocationException exp) {
}
This is not entirely accurate, but gives you a starting point.

Categories