Why does the below code work fine
Matcher reg = Pattern.compile("(A|B)\\w{2}(C|D)").matcher("");
while ((line=reader.readLine()) != null)
{
if (!loading || reg.reset(line).matches())
{
if (reg.reset(line).matches()) {
String id = reg.group(1);
}
}
}
but
while ((line=reader.readLine()) != null)
{
if (!loading || reg.reset(line).matches())
{
String id = reg.group(1);
}
}
throws IllegalSyntaxException?
I was surprised because I am already calling matches in the if condition. The expectation is that it returns the string matching the group, throws the exception instead.
java.lang.IllegalStateException: No match found
What am I missing?
If loading == false, reg.reset(line).matches() won't be executed, because !loading already is true. In your first example you then "again" check if there is a match and only then try to get the group. In your second example, you just assume that there is a match because you got there, which may not be true.
If the code you posted is all you do in this if-statement, you may get rid of the !loading check, as it doesn't matter if it's true or false - as soon as you find a match, you'll execute the code within the body, if you cannot find a match, it won't be executed.
Related
So here's a snippet of code I'm working on:
String direction = s.readLine();
System.out.println(direction);
if (direction.equals("up") != true && direction.equals("down") != true &&
direction.equals("left") != true && direction.equals("right") &&
direction.equals(null) != true) {
System.out.println("Invalid Solution file");
System.exit(0);
}
What it is supposed to do is read a line from a text file (using a BufferedReader) and then if the line isn't either a valid direction or blank then it should print "Invalid Solution" and exit.
The problem is that no matter what the direction string is the if statement still runs. I put in a println to check whether the direction was being read correctly but it seems absolutely fine. So why isn't the code working as intended?
Part of your problem is readability. Fix that and your problem is 90% solved:
private static List<String> DIRECTIONS = Arrays.asList("up", "down", "left", "right");
then
if (!DIRECTIONS.contains(direction)) {
System.out.println("Invalid Solution file");
System.exit(0);
}
The other 10% was how to check for null, which is direction == null, but if you use this code you don't need to, because contains(null) will conveniently return false.
You code is much more complex than it is needs to.
Consider this instead:
Set<String> validDirections = new HashSet<>(Arrays.asList("up", "down", ...
if (validDirections.contain(direction.toLowerCase()) {
// good ...
} else {
// bad ..
}
You can make validDirections a global constant for example; so it could be used in other places as well.
What I am trying to explain here is: your code is low-level. Low level code is hard to write, read, maintain and extend. Programming is always about creating good abstractions. Or vice versa: if you don't use abstractions, you end up with pretty abstract code, like the one you are showing here!
For example: if you need another direction, you have to put into your already way too complicated if condition. In my solution, you just put it into the statement that builds that Set.
Finally: your error message, is saying nothing. So, that string is bad; but why is it? Wouldn't it be better to at least print the string that caused the error?!
Here && direction.equals("right") I think you have done a mistake since it is on contradiction with the rest :
direction.equals("up") != true &&
direction.equals("down") != true &&
direction.equals("left") != true
You test the negation in the most of conditions but direction.equals("right") tests the affirmation.
Try it , it's the same thing but less verbose and more readable :
if (direction !=null && !direction.equals("up") &&
!direction.equals("down") &&
!direction.equals("left") &&
!direction.equals("right") ){
System.out.println("Invalid Solution file");
System.exit(0);
}
First, you should not use != true with a boolean statement, it is bad form. Rewrite like this:
direction !=null &&
!direction.equals("up") &&
!direction.equals("down") &&
!direction.equals("left") &&
!direction.equals("right")
Your error was that you did not include the != true part on one of your statements within the compound if. Replace with the above code to solve the issue.
I'm confused why you are using !=true when your .equals method already returns a boolean. Try this.
String direction = s.readLine();
System.out.println(direction);
if ( direction!=null && !direction.equals("up") && !direction.equals("down")&& !direction.equals("left")&& direction.equals("right")){
System.out.println("Invalid Solution file");
System.exit(0);
}
Try the following code:
boolean match = false;
if (direction.equals("up"))
{ match = true; }
if (direction.equals("down"))
{ match = true; }
if (direction.equals("left"))
{ match = true; }
if (direction.equals("right"))
{ match = true; }
if (direction.equals(null))
{ match = true; }
if (match == false){
System.out.println("Invalid Solution file");
System.exit(0);
}
You might also want to trim the direction string after reading from file.
The quals method returns a boolean so the result does not need to be compared with the true or false value. Also, I would start with null comparison - boolean expressions in Java are shortened so if this part will be fulfilled rest of the expression is not evaluated. The correct expression might look like this:
Â
if (direction == null || (!direction.equals("up") && !direction.equals("down") && !direction.equals("left") && !direction.equals ("right "))) {
}
But this code is not readable. You could use enums or list of Strings like below
List<String> directions = Arrays.asList("up", "down", "left", "right");
String direction = "readValue"
if (!directions.contains(direction)) {
System.out.println("Invalid direction");
System.exit(0)
}
I have a problem where I'm trying to get a parameter to match the format 'Uddd' where 'U' MUST be the letter U and 'ddd' can be any 3 digits from 0-9.
My current code:
//borrow method
public boolean borrow(String borrowerID)
{
//if the borrower ID matches the format 'Uddd'
if (borrowerID.matches("U([0-9]{3})"))
{
//if the status is available
if (status == 'A')
{
this.borrowerID = borrowerID;
this.status = 'O';
this.dateBorrowed = currentDate;
return true;
}
//is not available
else
{
return false;
}
}
//does not match format
else
{
return false;
}
}
For some reason it's not validating properly. When I tried inputting '1' as the parameter, it still returned true.
Is there something I'm missing?
It should not be possible for that method to return true if the input is "1". I can only suggest you ensure you are passing in "1" and that the method is the one being called.
That can be done with a simple debug statement at the top, something like:
System.out.println ("Calling correct function with [" + borrowerId + "]");
at the start of the function.
I'd also suggest a bit of clean-up to make the function easier to code and read, along the lines of:
// borrow method
public boolean borrow(String borrowerID)
{
// Temp debug statement.
// System.out.println ("borrow [" + borrowerId + "]");
// "Not available" or "invalid borrower" means reject request.
if (status != 'A')
return false;
if (! borrowerID.matches("U([0-9]{3})"))
return false;
// Okay to borrow.
this.borrowerID = borrowerID;
this.status = 'O';
this.dateBorrowed = currentDate;
return true;
}
This is a lot cleaner than all those return-else-do-something constructs, and it follows a "fail fast" paradigm.
Some people tend to dislike multiple return points but that's usually because they don't understand why they're considered bad (spaghetti code). With a short function like this, it doesn't pose a problem.
I get good results with your regex : "1" -> false, "UU123" -> false, "U1234" -> false, "U132" -> true.
but you can use \d instead of [0-9] :
borrowerID.matches("U(\\d{3})")
actually that's not possible.when input 1 it won't return true but it return false.may be your status is equal 'A' that should be reason to return true
String borrowerID="1";
boolean matches = borrowerID.matches("U([0-9]{3})");
System.out.println(matches);
output>>
false
if you only want to find is regex match or not then use this .or put a sout and check does status value.definitely it should be A
if (borrowerID.matches("U([0-9]{3})")) {
return true;
} else {
return false;
}
There is no issues with your regex
System.out.println("U888".matches("U([0-9]{3})"));
Output true
System.out.println("1".matches("U([0-9]{3})"));
Output false
Try debug your code, with few breakpoint inside your borrow function
You can also optimize your like
if (borrowerID.matches("U([0-9]{3})") && (status == 'A')) {
this.borrowerID = borrowerID;
this.status = 'O';
this.dateBorrowed = currentDate;
return true;
} else {
return false;
}
I don't understand onething, you are checking the status againist 'A' and inside assignin '0', does it make sense?(Anyway it's upto you)
Am checking validation of date using regex how it works for date but not for Year ? .Please help me to solve this issue.
Output :
false
true
false
true
Expected Output :
false
false
false
false
public static void main(String args[])
{
System.out.println(dateFormatValidate("ddMMyyyy","^(0?[1-9]|[12][0-9]|3[01])(0?[1-9]|1[012])((19|20)\\d\\d)?", "08s21988"));
System.out.println(dateFormatValidate("ddMMyyyy","^(0?[1-9]|[12][0-9]|3[01])(0?[1-9]|1[012])((19|20)\\d\\d)?", "08021s88"));
System.out.println(dateFormatValidate("ddMMyyyy","^(0?[1-9]|[12][0-9]|3[01])(0?[1-9]|1[012])((19|20)\\d\\d)?", "s8021988"));
System.out.println(dateFormatValidate("ddMMyyyy","^(0?[1-9]|[12][0-9]|3[01])(0?[1-9]|1[012])((19|20)\\d\\d)?", "0802198s"));
}
public static boolean dateFormatValidate(String format, String regex, String value) {
try {
if (value != null && !"".equals(value.trim()) && format != null && !"".equals(format.trim()))
{
if ((regex != null && !"".equals(regex.trim()) && Pattern.matches(regex, value)) || regex != null || "".equals(regex))
{
SimpleDateFormat dformat = new SimpleDateFormat(format);
dformat.setLenient(false);
dformat.parse(value);
return true;
} else
return false;
} else
return false;
} catch (Exception e) {
return false;
}
}
#sunleo I don't think so it has anything to do with your regex, as I have just tried your pattern on these four dates you provide and it doesn't capture any of them.
I would say the error is in this if:
if ((regex != null && !"".equals(regex.trim()) && Pattern.matches(regex, value)) || regex != null || "".equals(regex))
{
// your code
}
In the cases you provided in your main:
regex != null - all cases true
!"".equals(regex.trim()) - all cases true
Pattern.matches(regex, value)) - all cases false
regex != null - all cases true
"".equals(regex)) - all cases false
Which gives us following if:
if ( (true AND true AND false) OR true OR false )
which is the same as:
if ( false OR true OR false )
which gives in all cases:
true
So why you still managed to get two false outputs? Probably an exception was thrown here:
SimpleDateFormat dformat = new SimpleDateFormat(format);
dformat.setLenient(false);
dformat.parse(value);
So in your catch statement change return false to e.printStackTrace();.
Also my recommendation would be to rearrange this particular if first then check it for the cases that should be false (in this example all of them).
How?
First rearrange if then I would start with debugging and checking the if components to see their values and if they are computed correctly.
Also I think the regex is not correct at all (even if it's not the cause of the wrong output), if you always use ddMMyyyy format and only 19xx/20xx years, try this pattern:
^(0[1-9]|[1-2][0-9]|3[0-1])(0[1-9]|1[0-2])(19|20)\d{2}$
NOTE
I have not checked any of this (except regex) via any IDE as I do not have any here.
Is it possible to have multiple arguments for a .contains? I am searching an array to ensure that each string contains one of several characters. I've hunted all over the web, but found nothing useful.
for(String s : fileContents) {
if(!s.contains(syntax1) && !s.contains(syntax2)) {
found.add(s);
}
}
for (String s : found) {
System.out.println(s); // print array to cmd
JOptionPane.showMessageDialog(null, "Note: Syntax errors found.");
}
How can I do this with multiple arguments? I've also tried a bunch of ||s on their own, but that doesn't seem to work either.
No, it can't have multiple arguments, but the || should work.
!s.contains(syntax1+"") || !s.contains(syntax2+"") means s doesn't contain syntax1 or it doesn't contain syntax2.
This is just a guess but you might want s contains either of the two:
s.contains(syntax1+"") || s.contains(syntax2+"")
or maybe s contains both:
s.contains(syntax1+"") && s.contains(syntax2+"")
or maybe s contains neither of the two:
!s.contains(syntax1+"") && !s.contains(syntax2+"")
If syntax1 and syntax2 are already strings, you don't need the +""'s.
I believe s.contains("") should always return true, so you can remove it.
It seems that what you described can be done with a regular expression.
In regular expression, the operator | marks you need to match one of several choices.
For example, the regex (a|b) means a or b.
The regex ".*(a|b).*" means a string that contains a or b, and other then that - all is OK (it assumes one line string, but that can be dealt with easily as well if needed).
Code example:
String s = "abc";
System.out.println(s.matches(".*(a|d).*"));
s = "abcd";
System.out.println(s.matches(".*(a|d).*"));
s = "fgh";
System.out.println(s.matches(".*(a|d).*"));
Regular Exprsssions is a powerful tool that I recommend learning. Have a look at this tutorial, you might find it helpful.
There is not such thing as multiple contains.
if you require to validate that a list of string is included in some other string you must iterate through them all and check.
public static boolean containsAll(String input, String... items) {
if(input == null) throw new IllegalArgumentException("Input must not be null"); // We validate the input
if(input.length() == 0) {
return items.length == 0; // if empty contains nothing then true, else false
}
boolean result = true;
for(String item : items) {
result = result && input.contains(item);
}
return result;
}
Given a File and a Scanner object,
File simpleFile = ranFi.getSelectedFile();
Scanner text = new Scanner(simpleFile);
and these two commonplace statements:
while(text.hasNext())
{
String currentLine = text.nextLine();
I'm trying to use Scanner/String class logical statements in a single if-statement clause which reads first line of file under a given matching regular expressions, such as:
String fp100 = "[S][:][A-Ze0-1]";
String fp200 = "[S][:][A-Z0-1][A-Z0-1]";
//other regexes…
and then invoke the appropriate Scanner/String class methods in same if-statement clause to read to second and onward/acceptable lines. I've read javadoc up and down but haven't figured out yet. Using currentLine.matches(regex) and text.nextLine().matches(regex), this code compiled,
if(currentLine.matches(fp100)||currentLine.matches(fp200)||
currentLine.matches(fp300) && text.nextLine().matches(fp100)||
text.nextLine().matches(fp101) || text.nextLine().matches(fp200)||
text.nextLine().matches(fp201) || text.nextLine().matches(fp300)||
text.nextLine().matches(fp301))
{
but throws an No Such Element Exception immediately. What am I doing wrong?
Thank you in advance for your time. EDIT: I've included the stack trace, but removed the source code since this is project related.
I see two problems:
When you perform the if condition, text.nextLine() may not be available.
if you mean to say, execute the if when any of the currentLine Matches + any of the nextLine match as true then wrap || arguments in a brace as:
if((currentLine.matches(fp100)||currentLine.matches(fp200)||
currentLine.matches(fp300)) &&
(text.nextLine().matches(fp100)||
text.nextLine().matches(fp101) || text.nextLine().matches(fp200)||
text.nextLine().matches(fp201) || text.nextLine().matches(fp300)||
text.nextLine().matches(fp301)))
I think you wanted to write your while loop something like this:
while(text.hasNextLine()){
String currentLine = text.nextLine();
String nextLine = "";
if(text.hasNextLine())[
nextLine = text.nextLine();
}
/**ACC conditions*/
if((currentLine.matches(fp100)||currentLine.matches(fp200)
|| currentLine.matches(fp300))
&& (nextLine.matches(fp100)|| nextLine.matches(fp101)
|| nextLine.matches(fp200)
|| nextLine.matches(fp201) || nextLine.matches(fp300)
|| nextLine.matches(fp301)) {
//current line is OK
System.out.println(currentLine);
output.write(currentLine);
output.write("\n");
abc1List.add(currentLine);
lineOK++;
//next line is OK
System.out.println(nextLine);
output.write(nextLine);
output.write("\n");
abc1List.add(nextLine);
// <-- not sure if you want OK as 1 or 2 here
lineOK++;
} /**REJ conditions*/
else if(!currentLine.matches(fp100)||!currentLine.matches(fp101)||
!currentLine.matches(fp200)||!currentLine.matches(fp201)||
!currentLine.matches(fp300)||!currentLine.matches(fp301)){
System.out.println("invalid cfg; terminating....");
System.exit(0);
}
}//end of while
Your while loop should start with while(text.hasNextLine()) if you are using text.nextLine().matches(regex) inside the loop. Be careful. If text.hasNext() evaluates to true, it doesn't mean that text.nextLine() will be non-null.