I have this code:
public static void main(String[] args) {
List<Valtozas> lista = new ArrayList<Valtozas>();
try {
File fajl = new File("c://data//uzemanyag.txt");
Scanner szkenner = new Scanner(fajl, "UTF8");
while (szkenner.hasNext()) {
String sor = szkenner.nextLine();
String [] darabok = sor.split(";");
String szoveg = darabok[0];
Valtozas valtozas = new Valtozas(Integer.valueOf(darabok[0]), Integer.valueOf(darabok[1]), Integer.valueOf(darabok[2]));
lista.add(valtozas);
}
}
catch (Exception e) {
}
//3.FELADAT
System.out.println("3.Feladat: Változások száma: "+lista.size());
}
}
Here I want to convert the String to int, but I cant. I tried the Integer.Valueof(darabok[0]), but its not working. And nothing is happening, so the code is build, but quit from the while.
Based on the source code you have shown us, the problem is that there is a format mismatch between the input file and the program you are trying to read.
The program reads the file a line at a time, and splits it into fields using a single semicolon (with no whitespace!) as the file separator. Then it tries to parse the first three fields of each split line as integers.
For this to work the following must be true:
Every line must have at least three fields. (Otherwise you will get a ArrayIndexOutOfBound exception.)
The three fields must match the following regex: -?[0-9]+ i.e. an optional minus signed followed by one or more decimal digits.
The resulting number must be between Integer.MIN_VALUE and Integer.MAX_VALUE.
Elaborating on the above:
Leading and trailing whitespace characters are not allowed.
Embedded decimals markers and grouping characters are not allowed.
Scientific notation is not allowed.
Numbers that are too large or too small are not allowed.
Note that if any of the above constraints is not met, then the runtime system will throw an exception. Unfortunately, you surround your code with this:
try {
...
}
catch (Exception e) {
}
That basically ignores all exceptions by catching them and doing nothing in the handler block. You are saying to Java "if anything goes wrong, don't tell me about it!". So, naturally, Java doesn't tell you what is going wrong.
DON'T EVER DO THIS. This is called exception squashing, and it is a really bad idea1.
There are two ways to address this:
Print or log the stacktrace; e.g.
catch (Exception e) {
e.printStackTrace();
}
Remove the try / catch, and add throws IOException to the signature of your main method.
(You can't just remove the try / catch because new Scanner(fajl, "UTF8") throws IOException. That's a checked exception so must be handled or declared in the method signature.)
Once you have dealt with the exception properly you will get an exception message and stacktrace that tells you what is actually going wrong. Read it, understand it, and fix your program.
1 - It is like taping over the "annoying" red light that indicates that your car's oil level is low!
Related
i'm new to java programming and i'm trying to validate an email value using RegEx, the program should throw an exception when the user provides a wrong value, i managed to do this with an if-else. However, when i try to handle the error using a try-catch block the RegEx does not work anymore and the wrong value gets displayed anyways. How can i solve this?
here's the code
try {
String emailRegex = "^(.+)#(.+).(.+)$";
if(email.matches(emailRegex)) {
Pattern pattern = Pattern.compile(emailRegex);
System.out.println(pattern.matcher(email).matches());
} else {
throw new IllegalArgumentException();
}
} catch (IllegalArgumentException ex) {
System.out.println(ex.getLocalizedMessage());
}
This regular expression rejects valid email addresses. Even if you did fix it. For example, foo#bar is actually valid (top-level domains can contain MX records. A few do!). This is the general formula for 'is it valid email':
Does it contain spaces? If yes, reject.
Does it contain at least 1 #? If no, reject.
Is the last # at position 0 (i.e. at the start), or at the end? Reject.
Otherwise, pass. There are a few invalid emails that would nevertheless pass, but this is by and large no problem: foo#bar is not really legal, but the only real way to know that, is to send an email to it and request the user click a link inside it before they can continue. No regexp is ever going to figure out if the email address entered by a user is in fact a valid email address, let alone an email address that belongs to that user, hence, there is no real point in trying to go any further than that. You're attempting to catch honest typoes, not actually validate anything, because that is impossible. Note that it can easily become legal tomorrow - someone just needs to set up the bar top level domain and make sure there's an MX record for it in its DNS registration and voila. foo#bar is now legal.
Your regex is close to this ideal; you just want ^.+#.+$
NB: If you want to break spec and reject any email addresses to top-level domains, your regex is broken. Your intent is clearly to want foo#a.b, but you don't do that - that middle ., nestled between (.+), is still a regex dot operator, meaning: "any character". You'd want \\. for that instead. But, don't - as I said, TLDs are themselves rare as mail servers, but valid according to spec!
Fix this and your code 'works', but note that your code can go only one of two ways:
The regexp matches, in which case you again run the string through the regexp (seems rather pointless to do it twice!), and then trivially prints 'true'. The entire Pattern pattern = ...; System.out.println(...) might as well be System.out.println("true"); - that's what it will always do - yes, the regexp that just matched, is still going to match, of course.
The regexp does not match, in which case we get to the else block, which throws an exception. This then goes to the catch block which can only catch this (as nothing else throws IllegalArgumentEx here), and prints the 'localized message', which is null here.
So, this code prints true if it matches, and null if it does not. That seems.. weird. And is needlessly complicated if that's what you wanted.
Better:
class Test {
private static final Pattern EMAIL_PATTERN = Pattern.compile("^.+#.+$");
public static boolean isValidEmail(String email) {
return EMAIL_PATTERN.matcher(email).matches();
}
public static void main(String[] args) {
var keyboard = new Scanner(System.in);
while (true) {
System.out.print("Enter an email address: ");
String line = keyboard.nextLine().trim();
if (line.isEmpty()) System.exit(0);
if (isValidEmail(line)) {
System.out.println("Valid");
} else {
System.out.println("Not valid");
}
}
}
}
The try/catch block do not add anything useful here. You use try/catch when you want to transfer an error condition across method calls, not within the same method call, and not when the only meaningful data you can convey is a boolean flag. If that's all you have ('valid' or 'not valid'), almost always you just want a boolean.
If you really want the exception instead:
class Test {
private static final Pattern EMAIL_PATTERN = Pattern.compile("^.+#.+$");
public static void validateEmail(String email) throws IllegalArgumentException {
if (!EMAIL_PATTERN.matcher(email).matches()) {
throw new IllegalArgumentException("Email '" + email + "' is not valid");
}
}
public static void main(String[] args) {
var keyboard = new Scanner(System.in);
while (true) {
System.out.print("Enter an email address: ");
String line = keyboard.nextLine().trim();
if (line.isEmpty()) System.exit(0);
try {
validateEmail(line);
System.out.println("Valid");
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
}
}
I have a program that reads from a txt file each line and I'm supposed to handle the error when the line has more than 50 characters. I'm not very familiar with exceptions in Java, but is it ok if I just use an 'if' condition like this:
if(line.length() > 50) {
System.out.println("over 50 characters on this line");
return;
}
or should I declare a function like this:
static void checkLineLength(int lineLength) {
if(lineLength > 50) {
throw new ArithmeticException("over 50 characters");
}
}
and call it inside the main function?
checkLineLength(line.length());
LE: I've changed the exception handling block a bit:
static void checkLineLength(int lineLength) {
if(lineLength > 50) {
try {
throw new Exception("over 50 ch");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.exit(1);
}
}
}
Is it better? I see it works but I want to know if it's the professional way to do it.
The other answers so far concentrate on throwing and handling exceptions (with very good advice), but don't discuss the point whether exceptions are the best way of handling the long-text-line situation.
You write:
I'm supposed to handle the error when the line has more than 50
characters.
The wording "handle the error" needs interpretation / clarification. What are you supposed to do if a single line from the text file exceeds the 50-characters limit?
Use the first 50 characters and silently ignore the trailing rest?
Ignore the single line as faulty, but read the other lines?
Abort the whole file as unreadable because of syntax error, but keep the program running, e.g. to allow the user to select a different file?
Abort the whole program?
Depending on the answer to this question, exceptions might or might not be the answer for your problem.
Let's suppose, the method we talk about looks like this:
public List<FancyObject> readFromTextFile(File file) { ... }
It reads the text file line by line and puts one FancyObject per line into the result List.
In Java, a method can only either return a result or throw an exception. So in the first and second case, where you want to get a result (at least from the short lines), you can't throw an exception.
In the third case, I'd recommend to throw an exception as soon as you find a line longer than 50 characters (just as eddySoft suggested).
Even in the fourth case, I wouldn't put the System.exit() into the readFromTextFile() method, but in some higher-level method that's responsible for controlling the whole application, e.g. main(). It's a matter of readability or "principle of least surprise". Nobody expects a method named readFromTextFile() to be able to completely abort the Java Virtual machine. So, even in this case, I'd have the method throw its LineLimitException, and have main() catch that, inform the user and do the System.exit().
As long as you throw an Exception, both the approaches are fine. Only advantage while writing the method is you can reuse it.
Just one thing, System.out.println("over 50 characters on this line"); will log this in the console and silently move forward.
Throwing some exception like throw new ArithmeticException("over 50 characters"); , will break the flow.
EDIT:
METHOD 1:
You can use this piece of code:
static void checkLineLength(int lineLength) {
if(lineLength > 50) {
throw new ArithmeticException("over 50 characters");
}
}
OR
METHOD 2:
static void checkLineLength(int lineLength) {
if(lineLength > 50) {
throw new ArithmeticException("over 50 characters");
}
}
and call this method from somewhere in your code and put it in a try block:
try{
checkLineLength(line.length()); // call to the method
}
catch(Exception e){
e.printStackTrace(); // print the stacktrace if exception occurs
System.exit(1);
}
Define your Exception class. Example
class LineLimitException extends RuntimeException{
public LineLimitException(String message){
super(message);
}
}
Use your exception class in your logic
if(lineLength > 50) {
throw new LineLimitException("over 50 characters");
}
Language: Java, IDE: eclipse mars
The program is supposed to prompt the user (using JOptionPane) for a positive value. I'm trying to catch the invalid entries. My while statement catches the negative numbers but not the strings. When a negative number is entered, the prompt is shown again, but when a string value is entered, the exception is caught and the program moves on (when it should re prompt the user).
Once a positive value has been entered, the program assigns it to a value in another class. (We're learning the MVC OOP design pattern).
Double.isNaN(Double.parseDouble(h)) ---> can anyone help me find what am I missing?
// prompt to get bandwidth from user
// check for validity
// if invalid, prompt again
try{
h = JOptionPane.showInputDialog("Enter bandwidth as a positive number");
// loop until parsed string is a valid double
while (Double.isNaN(Double.parseDouble(h)) || Double.parseDouble(h) <=0) {
h = JOptionPane.showInputDialog("Enter bandwidth as a positive number");
}
// h has been set to valid double, set it to bandwidth
model.setBandwidth(Double.parseDouble(h));
}catch(NumberFormatException|NullPointerException NFE){
System.err.println("Caught exception: " + NFE.getMessage());
}
This is because of how parseDouble() works.
Throws:
NumberFormatException - if the string does not contain a parsable double.
(See here)
So if the String is not a double parseDouble() will not return NaN but throw an exception, which means your catch clause will be called.
To solve this problem maybe use recursively algorithm which will call your method again if an exception is thrown.
As 4castle already stated, you need to move your try/catch block inside your while loop.
However, for validating user input you can basically stick to the following pattern:
public Foo getUserInput() {
Foo result;
do {
try {
String s = requestUserInput(); // something like Scanner.nextLine()
result = parseUserInput(s); // something like Double.parseDouble(String)
}
catch(Exception exc) {
// maybe you want to tell the user what's happened here, too
continue;
}
}
while(!isValid(result)); // something like (0 < result)
return result;
}
I'm looking for an exception on how to catch an invalid String that is user input. I have the following code for a exception on an integer input:
try {
price = Integer.parseInt(priceField.getText());
}
catch (NumberFormatException exception) {
System.out.println("price error");
priceField.setText("");
break;
But I'm not aware of a specific exception for strings, the input is a simple JTextBox so the only incorrect input I can think of is if the user enters nothing into the box, which is what I'm looking to catch.
if (textField.getText().isEmpty())
is all you need.
Or maybe
if (textField.getText().trim().isEmpty())
if you also want to test for blank inputs, containing only white spaces/tabs.
You generally don't use exceptions to test values. Testing if a string represents an integer is an exception to the rule, because there is no available isInt() method in String.
You can do like
if (priceField.getText().isEmpty())
throw new Exception("priceField is not entered.");
You could check if priceField contains a string by using this:
JTextField priceField;
int price;
try {
// Check whether priceField.getText()'s length equals 0
if(priceField.getText().getLength()==0) {
throw new Exception();
}
// If not, check if it is a number and if so set price
price = Integer.parseInt(priceField.getText());
} catch(Exception e) {
// Either priceField's value's length equals 0 or
// priceField's value is not a number
// Output error, reset priceField and break the code
System.err.println("Price error, is the field a number and not empty?");
priceField.setText("");
break;
}
When the if-statement is true (If the length of priceField.getText() is 0) an exception gets thrown, which will trigger the catch-block, give an error, reset priceField and break the code.
If the if-statement is false though (If the length of priceField.getText() is greater or lower than 0) it will check if priceField.getText() is a number and if so it sets price to that value. If it not a number, a NumberFormatException gets thrown, which will trigger the catch-block etc.
Let me know if it works.
Happy coding :) -Charlie
if you want your exception to be thrown during the normal operation of the Java Virtual Machine, then you can use this
if (priceField.getText().isEmpty())
throw new RunTimeException("priceField is not entered.");
my application will have a text box which the user will edit with numbers (hopefully)
I am using Integer.parseInt() to convert the string into a integer, however, there's always the chance the user will not pass in numbers which will throw an exception during parseInt(). I am not sure what the convention is for error handling in GWT. Does this work?
int number = -1;
try {
number = Interger.parseInt(inputFromUser);
} catch (Exception e) {
// error handling like telling user to try again
}
If you want number-only boxes, use IntegerBox, LongBox, or DoubleBox. They already support rendering and parsing of, respectively, integer, long or double values using locale-aware renderers/parsers (based on NumberFormat).
You are on the right track. Just change Exception to NumberFormatException and you should be fine.