Struggling still with this after hours or research.. I have a simple helper class which is my first foray into try/catch error handling. I want to know if an input is valid against the type required and ask for a new input if it isn't... simple or so I thought. The class is being used in a simple term deposit calculator and is called multiple times (i.e. initial deposit, interest rate etc).
Here is the offending class, if this isn't sufficient to resolve I'll post up some additional snippets.
private Float inFloat;
private String temp;
private int inInt;
private String inString;
BufferedReader in = null;
boolean validInput = false;
public Float getFloat(String prompt) {
validInput = false;
do {
try {
in = new BufferedReader(new InputStreamReader(System.in));
System.out.print(prompt);
temp = in.readLine();
inFloat = Float.valueOf(temp);
validInput = true;
} catch (IOException e) {
System.out.println("Please enter a valid float value");
} finally {
try {
if (in != null) {
in.close();
}
} catch(IOException e) {
e.printStackTrace();
}
}
} while (validInput == false);
return inFloat;
}
Update - Fixed!!!
Thanks for the quick feedback... I managed to find another post that mentioned I shouldn't be closing off the BufferedReader and came up with the following adjustments so it now works. I'm now catching a NumberFormatException as well.. thanks for the tip :)
Not sure why it works now that I don't close off the BufferedReader... but I'll take the result!!
private Float inFloat;
private String temp;
private int inInt;
private String inString;
BufferedReader in = null;
boolean validInput = false;
public Float getFloat(String prompt) {
validInput = false;
do {
try {
in = new BufferedReader(new InputStreamReader(System.in));
System.out.print(prompt);
temp = in.readLine();
inFloat = Float.valueOf(temp);
validInput = true;
} catch (NumberFormatException e) {
System.out.println("Please enter a valid float value");
} catch (IOException e) {
e.printStackTrace();
}
} while (validInput == false);
return inFloat;
}
Float.valueOf(String s) will throw a NumberFormatException if it can't parse the input. Catch that one in addition to IOException.
In your code, NumberFormatException is thrown (if the input is invalid) but not catched inside the method, so the method will return immediatly after completing the finally block.
Related
I am creating a small algorithm and this is a part of it.
If the user enters non integer values, I want to output a message and let the user enter a number again:
boolean wenttocatch;
do
{
try
{
wenttocatch = false;
number_of_rigons = sc.nextInt(); // sc is an object of scanner class
}
catch (Exception e)
{
wenttocatch=true;
System.out.println("xx");
}
} while (wenttocatch==true);
I am getting a never ending loop and I can't figure out why.
How can I identify if the user enters some non integer number?
If the user enters a non integer number, how can I ask the user to enter again?
Update
When I am printing the exception I get 'InputMismatchException', what should I do?
The Scanner does not advance until the item is being read. This is mentioned in Scanner JavaDoc. Hence, you may just read the value off using .next() method or check if hasInt() before reading int value.
boolean wenttocatch;
int number_of_rigons = 0;
Scanner sc = new Scanner(System.in);
do {
try {
wenttocatch = false;
number_of_rigons = sc.nextInt(); // sc is an object of scanner class
} catch (InputMismatchException e) {
sc.next();
wenttocatch = true;
System.out.println("xx");
}
} while (wenttocatch == true);
You dont have to do a try catch. This code will do the trick for you :
public static void main(String[] args) {
boolean wenttocatch = false;
Scanner scan = new Scanner(System.in);
int number_of_rigons = 0;
do{
System.out.print("Enter a number : ");
if(scan.hasNextInt()){
number_of_rigons = scan.nextInt();
wenttocatch = true;
}else{
scan.nextLine();
System.out.println("Enter a valid Integer value");
}
}while(!wenttocatch);
}
Anytime you get an exception, wenttocatch is set to true and the program will be stuck in an infinite loop. As long as you don't get the exception you'll not get an infinite loop.
The logic if sc.nextInt() causing the error is this
1) wenttocatch is set to false
2) sc.nextInt() throws error
3) wenttocatch is set to true
4) repeat[because wenttocatch is true]
To solve this set wentocatch=false in catch statement
catch (Exception e) {
wenttocatch=false;
System.out.println("xx");
}
if you are doing more than you show here, use a counter[if your counting or a boolean if you are not], but unless you are doing more, do the first thing above
boolean wenttocatch;
int count = 0;
do{
try {
wenttocatch=false;
number_of_rigons=sc.nextInt(); // sc is an object of scanner class
} catch (Exception e) {
count++;
wenttocatch=true;
System.out.println("xx");
}
}while(wenttocatch==true && count < 1);
Answer Comment:
I think you want to get ints until a user doesn't enter anymore. Depending on your input one way of doing that is this
int number_of_rigons;
while((number_of_rigons = sc.nextInt()) != null){
//do something
}
you simply can use the hasNext(); method in java, instead of try and catch.
The hasNext() is a method of Java Scanner class that returns true if this scanner has another token in its input.
String[] stringArray = new String[lines];
int i = 0;
try (Scanner sc = new Scanner(file)) {
while (sc.hasNextLine()) {
String data=sc.nextLine();
stringArray[i] = data;
i++;
}
} catch (FileNotFoundException fileNotFoundException) {
System.err.println("Error opening file.");
throw new FileNotFoundException();
} catch (NoSuchElementException e) {
System.err.println("Error in file record structure");
throw new NoSuchElementException();
} catch (Exception e) {
e.printStackTrace();
}
/*added the scanner declaration inside try im new on programming its worked for me but I don't know if its good practice
*/ :
boolean wenttocatch;
do
{
try
{
Scanner sc=new Scanner(System.in);
wenttocoatch = false;
number_of_rigons = sc.nextInt();
}
catch (Exception e)
{
wenttocatch=true;
System.out.println("xx");
}
} while (wenttocatch==true);
....
try {
....
} catch (Exception e) {
sc.next();
wenttocatch=true;
System.out.println("xx");
}
ive gotten this far, but this doesnt work to read in the file, thats the part im stuck on. i know that you need to use the scanner, but im not sure what im missing here. i think it needs a path to the file also, but i dont know where to put that in
public class string
{
public static String getInput(Scanner in) throws IOException
{
{
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter file");
String filename =keyboard.next();
File inputFile = new File(filename);
Scanner input = new Scanner(inputFile);
String line;
while (input.hasNext())
{
line= input.nextLine();
System.out.println(line);
}
input.close();
}
if(filename.isEmpty())
{
System.out.println("Sorry, there has been an error. You must enter a string! (A string is some characters put together.) Try Again Below.");
return getInput(in);
}
else
{
return filename;
}
}
public static int getWordCount(String input)
{
String[] result = input.split(" ");
return result.length;
}
public static void main(String[] args)
{
DecimalFormat formatter = new DecimalFormat("0.##");
String input = getInput(new Scanner(System.in));
float counter = getWordCount(input);
System.out.println("The number of words in this string ("+input+") are: " + counter);
Scanner keyboard= new Scanner(System.in);
}
}
//end of code
First of all, when doing file I/O in Java, you should properly handle all exceptions and errors that can occur.
In general, you need to open streams and resources in a try block, catch all exceptions that happen in a catch block and then close all resources in a finally block. You should read up more on these here as well.
For using a Scanner object, this would look something like:
String token = null;
File file = null;
Scanner in = null;
try {
file = new File("/path/to/file.txt");
in = new Scanner(file);
while(in.hasNext()) {
token = in.next();
// ...
}
} catch (FileNotFoundException e) {
// if File with that pathname doesn't exist
e.printStackTrace();
} finally {
if(in != null) { // pay attention to NullPointerException possibility here
in.close();
}
}
You can also use a BufferedReader to read a file line by line.
BufferedReader reader = new BufferedReader(new FileReader("/path/to/file.txt"));
String line = null;
while ((line = reader.readLine()) != null) {
// ...
}
With added exception handling:
String line = null;
FileReader fReader = null;
BufferedReader bReader = null;
try {
fReader = new FileReader("/path/to/file.txt");
bReader = new BufferedReader(fReader);
while ((line = bReader.readLine()) != null) {
// ...
}
} catch (FileNotFoundException e) {
// Missing file for the FileReader
e.printStackTrace();
} catch (IOException e) {
// I/O Exception for the BufferedReader
e.printStackTrace();
} finally {
if(fReader != null) { // pay attention to NullPointerException possibility here
try {
fReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bReader != null) { // pay attention to NullPointerException possibility here
try {
bReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
In general, use the Scanner for parsing a file, and use the BufferedReader for reading the file line by line.
There are other more advanced ways to perform reading/writing operations in Java. Check out some of them here
I'm tinkering around on a small application to read some numbers in from a file. Everything runs well so far, but now I have encountered a problem I don't know how I can effectively fix it. If the user enters, unintentionally maybe, the wrong filename a FileNotFoundException will be thrown by the JVM, that I catch in my invoking method. Now I want to give him (the user) two another tries to enter the correct filename, but I don't know how I can invoke the method again which is opening the file when I'm actually in the catch-block below.
I will illustrate my transient solution below, but I'm not really sure if this is the most effective/elegant way to solve this problem:
//code omitted
int temp = 0;
while(true) {
filename = input.next();
try {
ex.fileOpen(filename);
}
catch(FileNotFoundException e) {
if(temp++ == 3) {
System.err.println("You have entered the filename three times consecutively wrongly");
return;
}
continue;
}
break;
}
//do some other stuff
input is a scanner which reads the user input and assigns it to the String-variable filename. fileOpen is a method which takes a filename, opens the file, reads the content and write all numbers in a vector.
So, I would really appreciate every support from the more experienced java programmers.
Greetings
Tom
You could use something like this,
public class AppMain {
public static void main(String[] args) throws IOException {
String filePath = input.next();
InputStream is = getInputStream(filePath);
int temp = 0;
while(is == null && temp < 3){
filePath = input.next();
is = getInputStream(filePath);
temp++;
}
if(is == null){
System.err.println("You have entered the filename three times consecutively wrongly");
return;
}
.........
.........
}
private static InputStream getInputStream(String filePath){
InputStream is = null;
try{
is = new FileInputStream(filePath);
return is;
}catch (IOException ioException) {
return null;
}
}
}
You may want to recursively call the method again:
public void doTheStuff(int attemptsLeft)
// ...
if (attemptsLeft == 0) {
System.err.println("You have entered the filename three times consecutively wrongly");
return;
}
filename = input.next();
try {
ex.fileOpen(filename);
}
catch(FileNotFoundException e) {
doTheStuff(attemptsLeft - 1);
return;
}
// ...
}
then simply call doTheStuff(3)
You can use exists method of the File class
For example fileOpen method can return true/false whether file exists
Think this will work.
int x = 0;
while (true){
filename = input.next();
try{
ex.fileOpen(filename);
break; // If it throws an exeption, will miss the break
}catch(FileNotFoundException e){
System.err.println("File not found, try again.");
}
if (x==2){
System.errprintln("You have entered the wrong file 3 times");
System.exit(0);
}
x++
}
Do not use exceptions to control your WorkFlow. Try something like this:
final int MAX_ERROR_ALLOWED=3;
public void readFile(String filename, int errorCount){
try{
File f = new File(filename);
if(!f.exists()){
String newFilename = input.next();
if(errorCount>=MAX_ERROR_ALLOWED){
throw new JustMyException();
}
readFile(newFilename, errorCount++);
}else{
//whatever you need to do with your file
}
}
}
How about something like this (pseudocode, not executable)?
// ...
for(int i = 0; i < 3; i++)
{
// User interaction to get the filename
if(attemptToOpenFile(ex))
{
break;
}
}
// Check if the file is open here and handle appropriately.
// ...
}
bool attemptToOpenFile(File ex, String filename) { // Forgot the class name for this
try {
ex.fileOpen(filename);
return true;
} catch(FileNotFoundException e) {
return false;
}
}
Alternatively, check if the file exists before calling fileOpen().
This question already has answers here:
How to insist that a users input is an int?
(7 answers)
Closed 9 years ago.
So i'm just learning java and I know this issue is very stupid, this is from the book Head Frist Java. When I try to put a letter instead of a number it crashes, how do I fix that? If I want it to say "pleasse try again with a number" when letter is entered.
public class Game {
public static void main(String[] args)
{
int numOfGuesses = 0;
GameHelper helper = new GameHelper();
SimpleDotCom theDotCom = new SimpleDotCom();
int randomNum = (int) (Math.random() * 5);
int[] locations = {randomNum, randomNum+1, randomNum+2};
theDotCom.setLocationCells(locations);
boolean isAlive = true;
while (isAlive == true)
{
String guess = helper.getUserInput("enter a number");
String result = theDotCom.checkYourself(guess);
numOfGuesses++;
if (result.equals("kill")) {
isAlive = false;
System.out.println("You took " + numOfGuesses + " guesses");
}
}
}
}
public class GameHelper {
private static final String alphabet = "abcdefg";
private int gridLength = 7;
private int gridSize = 49;
private int [] grid = new int[gridSize];
private int comCount = 0;
public String getUserInput(String prompt) {
String inputLine = null;
System.out.print(prompt + " ");
try {
BufferedReader is = new BufferedReader(
new InputStreamReader(System.in));
inputLine = is.readLine();
if (inputLine.length() == 0 ) return null;
} catch (IOException e) {
System.out.println("IOException: " + e);
}
return inputLine.toLowerCase();
}
public class SimpleDotCom {
int[] locationCells;
int numOfHits = 0;
public void setLocationCells(int[] locs)
{
locationCells = locs;
}
public String checkYourself(String stringGuess) {
int guess = Integer.parseInt(stringGuess);
String result = "miss";
for (int cell: locationCells)
{
if (guess == cell) {
result = "hit";
numOfHits++;
break;
}
}
if (numOfHits == locationCells.length)
{
result = "kill";
}
System.out.println(result);
return result;
}
In the following -
int guess = Integer.parseInt(stringGuess);
the parsing succeeds only if stringGuess contains some integer (within the range of [-2147483648 - 2147483647]. Otherwise, it fails with an exception.
To avoid that you have to make sure that stringGuess contains the right value.
Following is where the value comes from -
String guess = helper.getUserInput("enter a number");
String result = theDotCom.checkYourself(guess);
It's the getUserInput() method -
public String getUserInput(String prompt) {
String inputLine = null;
System.out.print(prompt + " ");
try {
BufferedReader is = new BufferedReader(new InputStreamReader(System.in));
inputLine = is.readLine();
if (inputLine.length() == 0)
return null; // this cannot be parsed
} catch (IOException e) {
System.out.println("IOException: " + e);
}
return inputLine.toLowerCase(); //this might not be an integer
}
And that's the part that you need to fix.
Following should do the job -
//...
BufferedReader is = new BufferedReader(new InputStreamReader(System.in));
while (true) { //keep reading
try {
inputLine = is.readLine();
int num = Integer.parseInt(inputLine); //make sure it's an integer
if(num > -1 && num < 10) { // if it is, and within [0-9]
break; // stop reading
}
} catch (Exception e) { // if not prompt again
System.out.println("pleasse try again with a number within [0-9]");
}
}
return inputLine; // no to lower case, it's a number
You can still better it up, by say just returning an int form this method, instead of String.
If you don't know if stringGuess is an integer or not, you can put Integer.parseInt(stringGuess) in a try { } catch construct. parseInt throws an exception if its input cannot be turned into an integer, so catch it. In the catch block, we know that it was not an integer. Otherwise it was an integer. Now do the logic you want to do (displaying a message, choosing to loop or not, etc)
(If you have not yet done exception handling, look up try and catch in Java)
as suggested by #patashu you can use try{ } catch() { }
as Integer.parseInt(argument) throws NumberFormatException if the argument is not a number(number in the form of string).
and about calling your input function again if user enters letter then you can simply do it by giving that particular input method a call inside catch block like:
try{
int guess = Integer.parseInt(stringGuess);
-----
-----
}
catch(NumberFormatException e){
System.out.println("Oooppps letter entered - try again with number ");
/**
now here make call to your method that takes input i.e getUserInput() in your case
**/
}
I have an assignment where I need to write a while loop code block that contains a trycatch statement. The try block retrieves each line from an input file, and invokes an isValid method I created to check if the format is correct, passing to it the line from the file. If there are no more lines to parse, runProgram is set to false, the while loop terminates. The catch block will catch an exception that I made. So far I have
public static void main(String[] args)
{
File file;
Scanner inputFile;
String fileName;
Scanner scan = new Scanner(file);
fileName = scan.nextLine();
boolean runProgram = true;
while(runProgram)
{
try
{
// for loop to check each line of my file
// invoke isValid
// Check if it's the last line in the file, and end program if so
}
catch(BankAccountException e)
{
System.out.println("Account Exception. Do you wish to quit? y/n");
String quit = scan.nextLine();
if(quit.equals("y"))
runProgram = false;
else
runProgram = true;
}
}
}
I just have no idea how to open a file, check the next line, use my isValid method (which is just a StringTokenizer that checks for the correct format), and closes when it reaches the end of the file.
Here is my isValid method:
private static boolean isValid(String accountLine) throws BankAccountException
{
StringTokenizer strTok = new StringTokenizer(accountLine, ";");
boolean valid = true;
if(strTok.countTokens() == 2)
{
if(strTok.nextToken().length() == 10)
{
if(!strTok.nextToken().matches(".*[0-9].*"))
{
valid = true;
}
}
}
else
valid = false;
return valid;
}
I also have a question with the above method. If I call .nextToken() twice, am I right in expecting the first iteration to deal with the first token, and the second to deal with the second? Or will they both just check the first token?
Just to get you started.
try {
BufferedReader reader = new BufferedReader(new FileReader(new File("/path/to/File")));
String currLine;
while ((currLine = reader.readLine()) != null) { // returns null at EOF
if (!isValid(currLine)) throw new BankAccountException();
}
} catch (BankAccountException e) {
// same
} finally {
reader.close();
}