I'm trying to write a getInt() method, which abstracts the extraction of an integer from the console, to the rest of my program.
Inside, is a try using resource -- the resource being a scanner; with a catch block for the inevitable InputMismatchException.
It captures valid inputs, fine; and catches false inputs.
However, after -- recursively -- trying to again capture the input, my scanner instantly throws a NoSuchElementException, which is obviously linked to the last mismatch error.
Do I need to clear something in the second scanner, perhaps left from the first?
private static int getInt(String name) {
try (Scanner scanner = new Scanner(System.in)) {
System.out.printf("Enter %s: ", name);
return scanner.nextInt();
} catch (InputMismatchException e) {
System.out.println("Invalid");
return getInt(name);
}
}
I already tried to instantiate the scanner out of the function, like so:
Scanner scanner = new Scanner(System.in);
getInt(scanner, name);
...
private static int getInt(Scanner scanner, String name) {
try {
System.out.printf("Enter %s: ", name);
return scanner.nextInt();
} catch (InputMismatchException e) {
System.out.println("Invalid");
return getInt(scanner, name);
}
}
Here, I simply get a stack over flow error, because the mismatch error recurs.
Related
Can someone explain and help me fix this program.
import java.util.*;
import java.io.*;
public class test {
public static void main(String[] args) {
Scanner key = new Scanner(System.in);
boolean clear;
int in = 0;
do {
clear = true;
try {
in = key.nextInt();
} catch (InputMismatchException e) {
System.out.println("Invalid");
clear = false;
}
} while (clear == false);
String stringIn = Integer.toString(in);
String[] dec = stringIn.split("");
for (int i = 1; i < (dec.length); i++) {
System.out.print(dec[i] + " ");
}
}
}
Whenever I enter a invalid input instead of an int, my program keeps looping "Invalid" instead of giving the option to enter a new value for in.
The problem is that if the scanner fails to find an input in the correct format, it will throw an exception and not read the input.
Because the scanner does not read the invalid int input, the next time nextInt is called, it will try to read the invalid input again, and miserably fails at it, printing another "invalid!"
So you need to read the input afterwards if it finds an invalid int:
// do this in the catch block:
key.next();
This makes sure that the next token is read.
Full code:
Scanner key = new Scanner(System.in);
boolean clear;
int in = 0;
do {
clear = true;
try {
in = key.nextInt();
} catch (InputMismatchException e) {
System.out.println("Invalid");
clear = false;
key.next();
}
} while (clear == false);
String stringIn = Integer.toString(in);
String[] dec = stringIn.split("");
for (int i = 1; i < (dec.length); i++) {
System.out.print(dec[i] + " ");
}
Check the API of the nextInt method:
This method will throw InputMismatchException if the next token cannot be translated into a valid int value as described below. If the translation is successful, the scanner advances past the input that matched.
Meaning, that if it's not successful - it will not advance and will try to execute nextInt over the illegal token over and over again failing every time.
Try adding next() into the exception catch clause, it should skip the token and read the next one then. next() reads a String, so it does not really care about the formatting, and will allow you to advance the position in the stream to read the next token.
The problem is that you are writing to the console inside the catch, so then when you call key.nextInt() in the try the program reads the value you print to the console, so an easy way to solve this is to add a line like: key.nextLine() inside the catch and that will solve your problem.
If a correct filename is entered, there's no issue. If an incorrect filename is entered, the infinite loop keeps telling the user to enter a file name. But it doesn't wait on the user to enter the filename. It keeps processing the first erroneous data in an infinite loop. I am using nextLine in the catch block which is supposed to clear the erroneous input. Also tried reset(). What am I doing wrong?
public static String reader() {
boolean fileCorrect = false;
// Holds the data from the file and is returned.
StringBuilder fromFile=new StringBuilder("");
// Loop until the user enter's a filename that the system can find.
do
{
System.out.println("\nEnter filename to open: ");
//Try with resources to open Scanner object for keyboard input
try (Scanner keyboard = new Scanner(System.in))
{
String fileName = keyboard.next();
// Trim leading/trailing spaces from filename
fileName = fileName.trim();
// The file object opened with try below
File iFile = new File(fileName);
//Attempt to open the file, which is automatically closed by try with resources.
try (Scanner fileInput = new Scanner(iFile))
{
//Read the file and append data to the string.
while (fileInput.hasNextLine())
{
fromFile = fromFile.append(fileInput.nextLine());
}
//If we make it this far, no need to loop.
fileCorrect = true;
}
// Catch specific first, a child of IOException. Most likely to happen.
catch (FileNotFoundException ex)
{
System.err.println(ex.getMessage() + ": File not found");
//ex.printStackTrace();
keyboard.nextLine();
}
// If the scanner somehow closed before data was read.
catch (IllegalStateException ex)
{
System.err.println(ex.getMessage() + ": Error reading from file");
//ex.printStackTrace();
keyboard.nextLine();
}
// Something else went wrong. Generic catch-all to keep the program from crashing.
catch (Exception ex)
{
System.err.println(ex.getMessage());
//ex.printStackTrace();
keyboard.nextLine();
}
}
catch (Exception ex)
{
// handle these
}
}
while (!fileCorrect);
Move this Scanner keyboard = new Scanner(System.in); to before the do-while loop
If you have it as try (Scanner keyboard = new Scanner(System.in)) - it will automatically call close on the System.in Scanner and next will not work
If you had a proper Exception handler
catch (Exception ex)
{
ex.printStackTrace();
}
you would see the message
java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:907)
at java.util.Scanner.next(Scanner.java:1416)
at Main.main(Main.java:38)
Use if else statements in your program with break keyword. If your input is the incorrect file name use break keyword so it would not continue the infinite block.
e.g
for()
{
if(filename==false)
{
break;
}
else
{
// continue your logic
}
Your problem is the first try block. Change it from this:
try (Scanner keyboard = new Scanner(System.in)) {
to this:
try {
Scanner keyboard = new Scanner(System.in);
The first will keep trying to read text and failing and trying again, etc. because the Scanner is closed, and the text can't be read as #ScaryWombat said in his comment
What would be the proper way to use the finally block to close out of the file that I was in : event.dat. If you could help me makes sense of this, I'd greatly appreciate it. I've literally spent 4 hours moving things around, playing with the code and searching for answers online, but to no avail. Code works great without that portion, but I need to know how it works for future instances. Thank you and have a good day!
I am having issues with this block:
finally{
fstream.close();
}
Which is located in the following code:
String answer;
String letter;
String inType = "";
double inAmount = 0;
double amount;
description();
GironEventClass newInput = new GironEventClass();
try{
File infile = new File("event.dat");
Scanner fstream = new Scanner(infile);
System.out.println("File Contents ");
while(fstream.hasNext())
{
inAmount = fstream.nextInt();
inType = fstream.next();
try{
newInput.donations(inType, inAmount);
}
catch(IllegalArgumentException a){
System.out.println("Just caught an illegal argument exception. ");
}
finally{
fstream.close();
}
}
System.out.println("Total Sales: " + newInput.getSale());
System.out.println("Donations: " + newInput.getDonated());
System.out.println("Expenses: " + newInput.getExpenses());
}
catch (FileNotFoundException e){
System.out.println("\nEvent.dat could not be opened. ");
}
do{
System.out.print("Are there any more items to add that were not in the text file? (Type 'Y' or 'N')");
answer = keyboard.next();
if (("Y".equals(answer)) || ("y".equals(answer)))
{
letter = inLetter();
amount = inAmount();
newInput.donations(letter, amount);
}
}while (("Y".equals(answer)) || ("y".equals(answer)));
newInput.display();
}
public static String inLetter(){
Scanner keyboard = new Scanner(System.in);
String result;
String resultTwo;
System.out.println("T = Tiket Sales");
System.out.println("D = Donations");
System.out.println("E = Expenses");
System.out.print("Please input an identifier ");
result = keyboard.nextLine();
resultTwo = result.toUpperCase();
return resultTwo;
}
public static double inAmount(){
Scanner keyboard = new Scanner(System.in);
double result;
System.out.println("Please input an amount ");
result = keyboard.nextInt();
if(result <= 0.0){
System.out.print("Please input a positive and non-zero amount ");
result = keyboard.nextInt();
}
return result;
}
public static void description(){
System.out.println("The program will ask you what amount is being spent on what.");
System.out.println(" ex: expenses, ticket sales, and profts.");
System.out.println("This program will help determine whether the event generated or lost money.");
}
This is how the scanner should work:
while scanner has object
read them ( one object per method's call)
when objects are done
close the reader.
Your problem is that you use the close function when the while conclusion is true. So you should put it outside of the while loop
The Try block attempts to do something.
The Catch block only executes if something went wrong during the Try block.
The Finally block executes after the Try block (and Catch block, if executed) EVERY time.
Your issue is that you attempt to close the fstream inside the while loop.
while(fstream.hasNext()) <----- referencing fstream
{
inAmount = fstream.nextInt();
inType = fstream.next();
try{
newInput.donations(inType, inAmount);
}
catch(IllegalArgumentException a){
System.out.println("Just caught an illegal argument exception. ");
}
finally{
fstream.close(); <---- closing said stream
}
}
Since you've closed the stream, this while loop should only ever execute once. That being said, close the fstream outside the while loop and your program should return to normal.
You can also move the while loop inside the try block, which would work as well.
You need to declare fstream outside the try block otherwise it will be not visible in the finally block.
File infile = null;
File infile = null;
try {
infile = new File("event.dat");
fstream = new Scanner(infile);
...
} catch ( ) {
...
} finally {
// You need to handle exceptions also here
infile.close();
fstream.close();
}
You can also use the new try with resources syntax and leave to the jvm the closure of your streams.
When I run my simple code and enter char instead of integer value which was supposed to be Entered.
Program, listed below is supposed to be terminated after printing "error please Enter integer value".
But this code, also printing the line after Occurrence of error
import java.util.InputMismatchException;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
System.out.println("enter value integer ");
Scanner sn = new Scanner(System.in);
try{
int a = sn.nextInt();
} catch (InputMismatchException ex){
System.out.println("error please enter integer value");
}
System.out.println("not terminating");
}
}
But this code, also printing the line after Occurrence of error
Because it is out side of try-catch, that is the advantage of exception handling.
Exception handling prevents the abnormal termination of program due to run time error. And that is what happened.
See also
exception handing docs
It is terminating, it just prints out the System.out first. This is as expected - it jumps into the catch block, and then continues.
System.out.println("enter value integer ");
Scanner sn = new Scanner(System.in);
try {
int a = sn.nextInt();
} catch (InputMismatchException ex) {
System.out.println("error please enter integer value");
// you are catching input mis match here
// exception will catch and program continues
}
System.out.println("not terminating"); // this is out side the try-catch
So you will get this line in your out put too.
After entering the catch block, flow continues on, so the next line to execute is the bottom print.
If you want to terminate from within the catch:
try {
int a = sn.nextInt();
} catch (InputMismatchException ex) {
System.out.println("error please enter integer value");
return; // program will end
}
If you want it to be terminated you need to re-throw the exception e.g.:
System.out.println("enter value integer ");
Scanner sn = new Scanner(System.in);
try {
int a = sn.nextInt();
} catch (InputMismatchException ex) {
System.out.println("error please enter integer value");
throw new RuntimeException(ex);
}
System.out.println("not terminating"); // this is out side the try-catch
That way the last system output would not be printed and you would get a stacktrace instead.
I'm trying to throw an exception (without using a try catch block) and my program finishes right after the exception is thrown. Is there a way that after I throw the exception, to then continue execution of my program? I throw the InvalidEmployeeTypeException which I've defined in another class but I'd like the program to continue after this is thrown.
private void getData() throws InvalidEmployeeTypeException{
System.out.println("Enter filename: ");
Scanner prompt = new Scanner(System.in);
inp = prompt.nextLine();
File inFile = new File(inp);
try {
input = new Scanner(inFile);
} catch (FileNotFoundException ex) {
ex.printStackTrace();
System.exit(1);
}
String type, name;
int year, salary, hours;
double wage;
Employee e = null;
while(input.hasNext()) {
try{
type = input.next();
name = input.next();
year = input.nextInt();
if (type.equalsIgnoreCase("manager") || type.equalsIgnoreCase("staff")) {
salary = input.nextInt();
if (type.equalsIgnoreCase("manager")) {
e = new Manager(name, year, salary);
}
else {
e = new Staff(name, year, salary);
}
}
else if (type.equalsIgnoreCase("fulltime") || type.equalsIgnoreCase("parttime")) {
hours = input.nextInt();
wage = input.nextDouble();
if (type.equalsIgnoreCase("fulltime")) {
e = new FullTime(name, year, hours, wage);
}
else {
e = new PartTime(name, year, hours, wage);
}
}
else {
throw new InvalidEmployeeTypeException();
input.nextLine();
continue;
}
} catch(InputMismatchException ex)
{
System.out.println("** Error: Invalid input **");
input.nextLine();
continue;
}
//catch(InvalidEmployeeTypeException ex)
//{
//}
employees.add(e);
}
}
If you throw the exception, the method execution will stop and the exception is thrown to the caller method. throw always interrupt the execution flow of the current method. a try/catch block is something you could write when you call a method that may throw an exception, but throwing an exception just means that method execution is terminated due to an abnormal condition, and the exception notifies the caller method of that condition.
Find this tutorial about exception and how they work - http://docs.oracle.com/javase/tutorial/essential/exceptions/
Try this:
try
{
throw new InvalidEmployeeTypeException();
input.nextLine();
}
catch(InvalidEmployeeTypeException ex)
{
//do error handling
}
continue;
If you have a method that you want to throw an error but you want to do some cleanup in your method beforehand you can put the code that will throw the exception inside a try block, then put the cleanup in the catch block, then throw the error.
try {
//Dangerous code: could throw an error
} catch (Exception e) {
//Cleanup: make sure that this methods variables and such are in the desired state
throw e;
}
This way the try/catch block is not actually handling the error but it gives you time to do stuff before the method terminates and still ensures that the error is passed on to the caller.
An example of this would be if a variable changed in the method then that variable was the cause of an error. It may be desirable to revert the variable.