Separating string from white space from a vector - java

So essentially I have an object of vectors and in a specific instance called 'comments' I have comments that actually have String in them and some that are just white space or have a single space. I tried to separate these from each other and I am running into trouble. Everything is outputted for some strange reason. Any thoughts? (display is a JTextArea)
for (int x = 0; x<dogParkProgramMain.infoVector.size(); x++)
{
if(dogParkProgramMain.infoVector.elementAt(x).getComment() == "//s" || dogParkProgramMain.infoVector.elementAt(x).getComment() == null){
System.out.println("Blank");
}
else{
display.append("Name: " + dogParkProgramMain.infoVector.elementAt(x).getFName() + " " + dogParkProgramMain.infoVector.elementAt(x).getLName() + newLine);
display.append("Comment: " + dogParkProgramMain.infoVector.elementAt(x).getComment() + newLine);
display.append("---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------" + newLine);
}
} // end first for loop

Not sure what you mean by \\s it's since you're not using regular expressions there. The following check should work:
String comment = dogParkProgramMain.infoVector.elementAt(x).getComment();
if (comment == null || comment.trim().isEmpty()) {
System.out.println("Blank");
}
trim() function will remove all leading and trailing spaces from the string meaning that if your string only contains spaces it would end up empty after trim. This code will check for any number of spaces as opposed to only one space mentioned in your question.

Related

Java: Issue when replacing Strings on loop

I'm building a small app which auto translates boolean queries in Java.
This is the code to find if the query string contains a certain word and if so, it replaces it with the translated value.
int howmanytimes = originalValues.size();
for (int y = 0; y < howmanytimes; y++) {
String originalWord = originalValues.get(y);
System.out.println("original Word = " + originalWord);
if (toReplace.contains(" " + originalWord.toLowerCase() + " ")
|| toCheck.contains('"' + originalWord.toLowerCase() + '"')) {
toReplace = toReplace.replace(originalWord, translatedValues.get(y).toLowerCase());
System.out.println("replaced " + originalWord + " with " + translatedValues.get(y).toLowerCase());
}
System.out.println("to Replace inside loop " + toReplace);
}
The problem is when a query has, for example, '(mykeyword OR "blue mykeyword")' and the translated values are different, for example, mykeyword translates to elpalavra and "blue mykeyword" translates to "elpalavra azul". What happens in this case is that the result string will be '(elpalavra OR "blue elpalavra")' when it should be '(elpalavra OR "elpalavra azul")' . I understand that in the first loop it replaces all keywords and in the second it no longer contains the original value it should for translation.
How can I fix this?
Thank you
you can sort originalValues by size desc. And after that loop through them.
This way you first replace "blue mykeyword" and only after you replace "mykeyword"
The "toCheck" variable is not explained what is for, and in any case the way it is used looks weird (to me at least).
Keeping that aside, one way to answer your request could be this (based only on the requirements you specified):
sort your originalValues, so that the ones with more words are first. The ones that have same number of words, should be ordered from more length to less.

Input Validation Loop

So my program allows a user to input a string then remove all occurrences of a character. If the character doesn't exist in the string then it should print an error message. Right now, I've created a loop to check each character in the string to create the new string without the character. I'm not sure how to create an input validation loop without printing an error message for each character that doesn't match the character the user wants to remove. I hope this makes sense!
Here is a portion of my code:
//REMOVE LOOP
System.out.println("Enter the character to remove");
String oldChar = keyboard.nextLine();
while ( indexEnd <= string.length() ) {
String substring = string.substring(indexStart, indexEnd);
indexStart++;
indexEnd++;
}
while ( substring.equals(oldChar) ) {
substring = string.substring(0, indexStart-1);
string = substring + string.substring(indexEnd - 1);
indexStart=0;
indexend=1;
}
}
Add a guard clause (a check) at the beginning.
It's best to avoid while loops and write something more readable.
public String removeCharacter(String text, String character) {
if(!text.contains(character)) {
throw new IllegalArgumentException("Character " + character + " not found in text " + text);
} else {
return text.replace(character, "");
}
}
Although Swifter's answer is great and more readable, here's another alternative:
Since we're just removing characters, we know that the character wasn't found if the resulting length stays the same.
public String remove(String text, String character) {
// save the original length because we are going to use it later
var origLength = text.length();
text = text.replace(character, "");
// check new length against original length
// - if they are the same, then 'character' wasn't found
if(origLength == text.length()) {
throw new IllegalArgumentException("Character " + character + " not found.");
}
return text;
}
Technically this is more performant since there's just one pass through the string (although in reality this is negligible).

java: code keeps looping

The below code is giving me a headache: It's supposed to jump out of the do--while loop after replacing all \n's, but it doesn't. Any ideas how to solve this?
public String invoerenTemplate(){
String templateGescheiden = null;
String teHerkennenTemplate = Input.readLine();
String uitvoer = teHerkennenTemplate;
do {
templateGescheiden = teHerkennenTemplate.substring(0, teHerkennenTemplate.indexOf(" "));
templateGescheiden += " ";
if (templateGescheiden.charAt(0) == '\\' && templateGescheiden.charAt(1) == 'n') {
teHerkennenTemplate = teHerkennenTemplate.replace(templateGescheiden, "\n");
uitvoer = uitvoer.replace(templateGescheiden, "\n");
}
teHerkennenTemplate = teHerkennenTemplate.substring(teHerkennenTemplate.indexOf(" "));
System.out.println(uitvoer);
} while (teHerkennenTemplate.length() > 0);
return uitvoer;
}
EDIT:
I now placed this line: teHerkennenTemplate.trim(); just beneath my if-statement, but now it gives me a StringIndexOutOfRange: 0 error at my first line of my if-statement
I have noticed a couple of problems with the above code, although it is difficult to tell why you are taking the approach that you are to the solution.
The main thing I noticed is that your replace statements do NOT remove the \n characters
teHerkennenTemplate = teHerkennenTemplate.replace(templateGescheiden, "\n");
uitvoer = uitvoer.replace(templateGescheiden, "\n");
From Java Documentation:
replace(char oldChar, char newChar):
Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar.
So, you are replacing your string templateGescheiden with \n each time you loop.
Another issue would be the improper shortening of your teHerkennenTemplate string each loop, which is causing it not to terminate correctly. It will always shorten from the next space character to the end of the string (inclusive) - meaning it will never be an empty string, but will always have a " ".
My advice would be to debug and go step-by-step to see where the shortening and string manipulation is not doing what you want, then evaluate why and modify the code appropriately
There's a variety of things wrong with the code:
the index of a carriage return is found in the string with indexOf("\n").
the substring of teHerkennenTemplate isn't taking into account that it starts with a space, which cause the loop to continue forever.
The simplest way to do what you want is with a regular expression:
"test \n test \n".replaceAll("\n", "")
Will return:
"test test "
If you're set on using a loop then this will do the same:
public static String invoerenTemplate(String teHerkennenTemplate)
{
StringBuilder result = new StringBuilder();
while (teHerkennenTemplate.length() > 0)
{
int index = teHerkennenTemplate.indexOf("\n");
result.append(index > -1 ? teHerkennenTemplate.substring(0, index) : teHerkennenTemplate);
teHerkennenTemplate = teHerkennenTemplate.substring(index + 1, teHerkennenTemplate.length());
}
return result.toString();
}

Something crazy happens with StringBuilder.append(String str);

I've got a problem with my java-project.
following function should deliver a String for a SQL-Statement:
private static String createInsertString(Pat p)
{
StringBuilder x = new StringBuilder();
x.append("" + p.getPatnr() +","+ p.getSvnr());
java.sql.Date andat = null,gebdat;
if(p.getAndat()==null)
andat=null;
else
andat=new java.sql.Date(p.getAndat().getTimeInMillis());
if(p.getGebdat()==null)
gebdat=null;
else
gebdat=new java.sql.Date(p.getGebdat().getTimeInMillis());
x.append("," + andat==null?"null":andat);
x.append("," + p.getTele()==null?"null":p.getTele());
x.append("," + p.getVName() +","+ p.getNname());
x.append("," + p.getKk()==null?"null":p.getKk());
x.append("," + gebdat==null?"null":gebdat);
x.append("," + p.getAdrplzort()==null?"null":6);
x.append("," + p.getAdrstr()==null?"null":p.getAdrstr());
x.append("," + p.getAdrhnr()==null?"null":p.getAdrhnr());
s.append("," + p.getReplzort()==null?"null":p.getReplzort().getPlzortnr());
x.append("," + p.getRestr()==null?"null":p.getRestr());
x.append("," + p.getRehnr()==null?"null":p.getRehnr());
x.append("," + p.getLevel());
x.append("," + p.getCon()==null?"null":p.getCon());
x.append("," + (p.isPa()?"y":"n")+","+ (p.isLonly()?"y":"n") +","+ (p.isGest()?"y":"n"));
x.append("," + p.getBem()==null?"null":p.getBem());
x.append("," + (p.isKat1()?'y':'n') +","+ (p.isKat2()?'y':'n') +","+ (p.isKat3()?'y':'n'));
System.out.println(x);
return x.toString();
}
the output is
6,6465136nullnull,Jürgen,Wieslernullnull6nullnullnullnull,0null,n,n,nnull,n,n,n
but it should be like this:
6,6465136,null,null,Jürgen,Wiesler,null,null,6,null,null,null,null,0,null,n,n,n,null,n,n,n
Anyone an Idea?
I'm using jdk 1.7 on debian(64-bit)
The problem is how the operators bind. Look at this:
x.append("," + andat==null?"null":andat);
Now think of it as:
x.append(("," + andat) == null ? "null" : andat);
The LHS is never going to be null, so it's always just appending andat... and that still converts to "null" if the reference is null, because that's the default behaviour of StringBuilder.
Your code is much more complicated - and inefficient - than it needs to be. Consider rewriting it as:
private static String createInsertString(Pat p)
{
StringBuilder x = new StringBuilder();
java.sql.Date andat = p.andat == null ? null
: new java.sql.Date(p.getAndat().getTimeInMillis());
java.sql.Date gebdat = p.getGebdat() == null ? null
: new java.sql.Date(p.getGebdat().getTimeInMillis());
x.append(p.getPatnr()).append(",")
.append(p.getSvnr()).append(",")
.append(andat).append(",")
.append(p.getTele()).append(",")
// etc
return x.toString();
}
Note that I think you had a bug in the original:
x.append("," + p.getVName() +","+ p.getNname());
Where these meant to be calling two different getters?
You are misusing .append() by putting concatenations inside them! This misses the entire point of what StringBuilder is supposed to be used for.
x.append("," + andat==null?"null":andat);
should be
x.append(",").append( andat == null ? "null" : andat);
which would be the correct logic to make your ternary operator work as you intended.
.append() returns a reference to the StringBuilder so that you can chain .append() calls as much as you need.
Anytime you are putting a string concatenation inside of .append() you are just creating more intermediate String objects that eat up memory, cpu cycles and then use more resources as they now need to be garbage collected.
Also you should pre-allocate your StringBuilder with a default size that is slightly bigger than what you expect your contents to be to avoid wasted allocations and garbage creation.
See the Javadoc for the StringBuilder(int) constructor.
The problem comes from your '+'.
If you use a StringBuilder, don't use '+': it is not efficient
"," + andat==null?"null":andat results in ",null"==null?"null":andat if andat is null.
The '+' string concatenation has priority over the ternary operator
When you use the '+' with String your compiler actually translates that to a StringBuilder (or a StringBuffer before Java5)
So having
String s = a + b + c;
is actually translated to:
String s = new StringBuilder().append(a).append(b).append(c).toString().
Therefore using + within a StringBuilder is counter-productive as you create additional unecessary StringBuilder.

Algorithm to detect how many words typed, also multi sentence support (Java)

Problem:
I have to design an algorithm, which does the following for me:
Say that I have a line (e.g.)
alert tcp 192.168.1.1 (caret is currently here)
The algorithm should process this line, and return a value of 4.
I coded something for it, I know it's sloppy, but it works, partly.
private int counter = 0;
public void determineRuleActionRegion(String str, int index) {
if (str.length() == 0 || str.indexOf(" ") == -1) {
triggerSuggestionList(1);
return;
}
//remove duplicate space, spaces in front and back before searching
int num = str.trim().replaceAll(" +", " ").indexOf(" ", index);
//Check for occurances of spaces, recursively
if (num == -1) { //if there is no space
//no need to check if it's 0 times it will assign to 1
triggerSuggestionList(counter + 1);
counter = 0;
return; //set to rule action
} else { //there is a space
counter++;
determineRuleActionRegion(str, num + 1);
}
} //end of determineactionRegion()
So basically I find for the space and determine the region (number of words typed). However, I want it to change upon the user pressing space bar <space character>.
How may I go around with the current code?
Or better yet, how would one suggest me to do it the correct way? I'm figuring out on BreakIterator for this case...
To add to that, I believe my algorithm won't work for multi sentences. How should I address this problem as well.
--
The source of String str is acquired from textPane.getText(0, pos + 1);, the JTextPane.
Thanks in advance. Do let me know if my question is still not specific enough.
--
More examples:
alert tcp $EXTERNAL_NET any -> $HOME_NET 22 <caret>
return -1 (maximum of the typed text is 7 words)
alert tcp 192.168.1.1 any<caret>
return 4 (as it is still at 2nd arg)
alert tcp<caret>
return 2 (as it is still at 2nd arg)
alert tcp <caret>
return 3
alert tcp $EXTERNAL_NET any -> <caret>
return 6
It is something like shell commands. As above. Though I think it does not differ much I believe, I just want to know how many arguments are typed. Thanks.
--
Pseudocode
Get whole paragraph from textpane
if more than 1 line -> process the last line
count how many arguments typed and return appropriate number
else
process current line
count how many arguments typed and return appropriate number
End
This uses String.split; I think this is what you want.
String[] texts = {
"alert tcp $EXTERNAL_NET any -> $HOME_NET 22 ",
"alert tcp 192.168.1.1 any",
"alert tcp",
"alert tcp ",
"alert tcp $EXTERNAL_NET any -> ",
"multine\ntest\ntest 1 2 3",
};
for (String text : texts) {
String[] lines = text.split("\r?\n|\r");
String lastLine = lines[lines.length - 1];
String[] tokens = lastLine.split("\\s+", -1);
for (String token : tokens) {
System.out.print("[" + token + "]");
}
int pos = (tokens.length <= 7) ? tokens.length : -1;
System.out.println(" = " + pos);
}
This produces the following output:
[alert][tcp][$EXTERNAL_NET][any][->][$HOME_NET][22][] = -1
[alert][tcp][192.168.1.1][any] = 4
[alert][tcp] = 2
[alert][tcp][] = 3
[alert][tcp][$EXTERNAL_NET][any][->][] = 6
[test][1][2][3] = 4
The codes provided by polygenelubricants and helios work, to a certain extent. It addresses the aforementioned problem I'd stated, but not with multi-lines. helios's code is more straightforward.
However both codes did not address the problem when you press enter in the JTextPane, it will still return back the old count instead of 1 as the split() returns it as one sentence instead of two.
E.g. alert tcp <enter is pressed>
By right it should return 1 since it is a new sentence. It returned 2 for both algorithms.
Also, if I highlight all and delete both algorithms will throw NullPointerException as there is no string to be split.
I added one line, and it solved the problems mentioned above:
public void determineRuleActionRegion(String str) {
//remove repetitive spaces and concat $ for new line indicator
str = str.trim().replaceAll(" +", " ") + "$";
String[] lines = str.split("\r?\n|\r");
String lastLine = lines[lines.length - 1];
String[] tokens = lastLine.split("\\s+", -1);
int pos = (tokens.length <= 7) ? tokens.length : -1;
triggerSuggestionList(pos);
System.out.println("Current pos: " + pos);
return;
} //end of determineactionRegion()
With that, when split() parses the str, the "$" will create another line, which will be the last line regardless, and the count now will return to one. Also, there will not be NullPointerException as the "$" is always there.
However, without the help of polygenelubricants and helios, I don't think I will be able to figure it out so soon. Thanks guys!
EDIT: Okay... apparently split("\r?\n|\r",-1) works the same. Question is should I accept polygenelubricants or my own? Hmm.
2nd EDIT: One thing bad about concatenating '%' to the end of the str, lastLine.endsWith(" ") == true will return false. So have to use split("\r?\n|\r",-1) and lastLine.endsWith(" ") == true for the complete solution.
What about this: get last line, count what's between spaces...
String text = ...
String[] lines = text.split("\n"); // or \r\n depending on how you get the string
String lastLine = lines[lines.length-1];
StringTokenizer tokenizer = new StringTokenizer(lastLine, " ");
// note that strtokenizer will ignore empty tokens, it is, what is between two consecutive spaces
int count = 0;
while (tokenizer.hasMoreTokens()) {
tokenizer.nextToken();
count++;
}
return count;
Edit you could control if you have a final space (lastLine.endsWith(" ")) so you are starting a new word or whatever, it's a basic approach for you to make it up :)
Is the sample line representative? An editor for some rule based language (ACLs)?
How about going for a full Information Extraction/named entity recognition solution, the one that will be able to recognize entities (keywords, ip addresses, etc)? You don't have to write everything from scratch, there're existing tools and libraries.
UPDATE: Here's a piece of Snort code that I believe does the parsing:
Function ParseRule()
if (*args == '(') {
// "Preprocessor Rule detected"
} else {
/* proto ip port dir ip port r*/
toks = mSplit(args, " \t", 7, &num_toks, '\\');
/* A rule might not have rule options */
if (num_toks < 6) {
ParseError("Bad rule in rules file: %s", args);
}
..
}
otn = ParseRuleOptions(sc, rtn, roptions, rule_type, protocol);
..
mSplit is defined in mstring.c, a function to split a string into tokens.
In your case, ParseRuleOptions should return one for the whole string inside brackets I guess.
UPDATE 2: btw, is your first example correct, since in snort, you can add options to rules? For example this is a valid rule being written (options section not completed):
alert tcp any any -> 192.168.1.0/24 111 (content:"|00 01 86 a5|"; <caret>
In some cases you can have either 6 or 7 'words', so your algorithm should have a bit more knowledge, right?

Categories