handle Exceptions casued by input scanner - java

I'm trying to do encode/decode program and I'm encountering all kinds of Exceptions here!
problems that is popping up caused by multiple/single scanner/s:
InputMismatchException | NumberFormatException (ATTEMPT 2)
NoSuchElementException (ATTEMPT 3)
Before going through I would like to address that this is not a duplicate and I have looked up multiple problems on StackOverFlow of this kind and none helped me really much.
Similiar problems that I've looked at: link1 link2
Note that the wished end results are like the results of the first attempt but with somehow better cleaner exception handling and closed scanners.
FIRST ATTEMPT
Now this program gives me the desired results but its a bad programming to have two scanners and one of them ( input method scanner ) is never closed:
public static void main(String[] args) {
Scanner sc=new Scanner (System.in);
int choice = 0;
do {
System.out.println("This program to encode or decode a byte array " +
"\n (o_O) Choices are: " +
"\n 1: Press 1 to enter the encode mode" +
"\n 2: Press 2 to enter the decode mode" +
"\n 3: Press 3 to Exit!");
try {
//it has to be parseInt because if you used sc.nextInt() the program will go nuts even with try catch.
choice=Integer.parseInt(sc.next());
//choice=sc.nextInt();
/*Question: why when i use this with the existing try catch i the program work for ever but when i use Integer.parseInt(sc.nextLine())
* the program would normally ask for another value?
*/
} catch (InputMismatchException | NumberFormatException e) {
System.out.println("invalid type or format!");
} catch (NoSuchElementException e) {
System.out.println("no such");
//break; if i uncomment this the programm will work For Ever
}
switch(choice){
case 1 :
System.out.println("entering the encode mode!");
countAndEncode( input() );
break;
case 2 :
countAndDecode( input() );
break;
case 3 :
System.out.println("exiting...");
break;
default :
System.out.println("please enter a valid option and valid format!");
}
} while (choice!=3);
sc.close();
}
public static byte [] input() {
//arrayList because we dont know the size of the array its like StringBuilder
//ArrayList<Byte> inArray = new ArrayList<Byte>();
//according to StackOverflow using ArrayList to store bytes is inefficient
Scanner inScanner=new Scanner (System.in);
ByteArrayOutputStream inArray= new ByteArrayOutputStream();
System.out.println("enter a sequence of ints please! ");
System.out.println("non-int will terminate the input!");
while (inScanner.hasNext()) {
byte i;
try {
i = inScanner.nextByte();
inArray.write(i);
} catch (InputMismatchException e) {
System.out.println("input terminated!");
break;
}
}
//System.out.println(Arrays.toString(inArray.toByteArray()));
//inScanner.close();
return inArray.toByteArray();
}
OUTPUT OF FIRST ATTEMPT:
This is a program to encode or decode bytes based on RLE ALgorithm
(o_O) Choices are:
1: Press 1 to enter the encode mode
2: Press 2 to enter the decode mode
3: Press 3 to Exit!
1
entering the encode mode!
enter a sequence of bytes please!
non-int will terminate the input!
1
1
3
e
input terminated!
[1, 1, 3]
the encoded list is [-1, 1, 2, 3]
This is a program to encode or decode bytes based on RLE ALgorithm
(o_O) Choices are:
1: Press 1 to enter the encode mode
2: Press 2 to enter the decode mode
3: Press 3 to Exit!
At it goes forever without errors.
SECOND ATTEMPT
so what i did after one fellow of you guys sugessted to take a look at this problem link is this:
Now i didnt close the input scanner and i gave the input method a scanner as a parameter:
public static void main(String[] args) {
Scanner sc=new Scanner (System.in);
int choice = 0;
do {
System.out.println("This is a program to encode or decode bytes based on RLE ALgorithm" +
"\n (o_O) Choices are: " +
"\n 1: Press 1 to enter the encode mode" +
"\n 2: Press 2 to enter the decode mode" +
"\n 3: Press 3 to Exit!");
try {
//it has to be parseInt because if you used sc.nextInt() the program will go nuts even with try catch.
choice=Integer.parseInt(sc.next());
//choice=sc.nextInt();
/*Question: why when i use this with the existing try catch i the program work for ever but when i use Integer.parseInt(sc.nextLine())
* the program would normally ask for another value?
*/
} catch (InputMismatchException | NumberFormatException e) {
System.out.println("invalid type or format!");
} catch (NoSuchElementException e) {
System.out.println("no such");//TODO SOLVE IT PLEASE ITS DRIVING ME CRAZYYYYYYYYYYY!!!!!!!
break;
}
switch(choice){
case 1 :
System.out.println("entering the encode mode!");
countAndEncode( input(sc) );
break;
case 2 :
//countAndDecode( input(sc) );
break;
case 3 :
System.out.println("exiting...");
break;
default :
System.out.println("please enter a valid option and valid format!");
}
} while (choice!=3);
sc.close();
}
/**
* with this method user will be able to give the desired sequence of bytes.
* #return a byte array to be encoded.
*/
public static byte [] input(Scanner inScanner) {
//arrayList because we dont know the size of the array its like StringBuilder
//ArrayList<Byte> inArray = new ArrayList<Byte>();
//according to StackOverflow using ArrayList to store bytes is inefficient
//Scanner inScanner=new Scanner (System.in);
ByteArrayOutputStream inArray= new ByteArrayOutputStream();
System.out.println("enter a sequence of bytes please! ");
System.out.println("non-int will terminate the input!");
while (inScanner.hasNext()) {//TODO THIS MIGHT BE THE REASON FOR THE above "SUCH"
byte i;
try {
i = inScanner.nextByte();
inArray.write(i);
} catch (InputMismatchException e) {
System.out.println("input terminated!");
break;
}
}
System.out.println(Arrays.toString(inArray.toByteArray()));
//inScanner.close(); dont close it because it cant be re-opened
return inArray.toByteArray();
}
Doing so doesn't give me the desired results at all:
After choosing one to encode and receive the encoded bytes I will get stuck forever in the encoding mode and the InputMismatchException | NumberFormatException clause will get activated so I cant get a chance to select a new input!
This is a program to encode or decode bytes based on RLE ALgorithm
(o_O) Choices are:
1: Press 1 to enter the encode mode
2: Press 2 to enter the decode mode
3: Press 3 to Exit!
1
entering the encode mode!
enter a sequence of bytes please!
non-int will terminate the input!
1
e
input terminated!
1
the encoded list is 1
This is a program to encode or decode bytes based on RLE ALgorithm
(o_O) Choices are:
1: Press 1 to enter the encode mode
2: Press 2 to enter the decode mode
3: Press 3 to Exit!
invalid type or format!
entering the encode mode!
enter a sequence of bytes please!
non-int will terminate the input!
NOTES:
1.commenting sc.close() in main caused the exact same error as above..
2.that moving scanner above main and declaing it as a global static variable did the exact thing as the faild above results.
THIRD ATTEMPT
now i left both of the closed each scanner and this activated the NoSuchElementException in main Take a look:
public static void main(String[] args) {
Scanner sc=new Scanner (System.in);
int choice = 0;
do {
System.out.println("This is a program to encode or decode bytes based on RLE ALgorithm" +
"\n (o_O) Choices are: " +
"\n 1: Press 1 to enter the encode mode" +
"\n 2: Press 2 to enter the decode mode" +
"\n 3: Press 3 to Exit!");
try {
//it has to be parseInt because if you used sc.nextInt() the program will go nuts even with try catch.
choice=Integer.parseInt(sc.next());
//choice=sc.nextInt();
/*Question: why when i use this with the existing try catch i the program work for ever but when i use Integer.parseInt(sc.nextLine())
* the program would normally ask for another value?
*/
} catch (InputMismatchException | NumberFormatException e) {
System.out.println("invalid type or format!");
} catch (NoSuchElementException e) {
System.out.println("no such");//TODO SOLVE IT PLEASE ITS DRIVING ME CRAZYYYYYYYYYYY!!!!!!!
break;
}
switch(choice){
case 1 :
System.out.println("entering the encode mode!");
countAndEncode( input() );
break;
case 2 :
//countAndDecode( input() );
break;
case 3 :
System.out.println("exiting...");
break;
default :
System.out.println("please enter a valid option and valid format!");
}
} while (choice!=3);
sc.close();
}
/**
* with this method user will be able to give the desired sequence of bytes.
* #return a byte array to be encoded.
* #throws IOException
*/
public static byte [] input() {
//arrayList because we dont know the size of the array its like StringBuilder
//ArrayList<Byte> inArray = new ArrayList<Byte>();
//according to StackOverflow using ArrayList to store bytes is inefficient
Scanner inScanner=new Scanner (System.in);
ByteArrayOutputStream inArray= new ByteArrayOutputStream();
System.out.println("enter a sequence of bytes please! ");
System.out.println("non-int will terminate the input!");
while (inScanner.hasNext()) {//TODO THIS MIGHT BE THE REASON FOR THE above "SUCH"
byte i;
try {
i = inScanner.nextByte();
inArray.write(i);
} catch (InputMismatchException e) {
System.out.println("input terminated!");
break;
}
}
System.out.println(Arrays.toString(inArray.toByteArray()));
inScanner.close();
return inArray.toByteArray();
}
in this attempt i , at least, might know what is causing the NoSuchElementException to jump up and i think its because closing one scanner will close the input stream for the whole code.(correct me if im wrong!)
OUTPUT FOR THE THIRD ATTEMPT IS:
This is a program to encode or decode bytes based on RLE ALgorithm
(o_O) Choices are:
1: Press 1 to enter the encode mode
2: Press 2 to enter the decode mode
3: Press 3 to Exit!
1
entering the encode mode!
enter a sequence of bytes please!
non-int will terminate the input!
-1
-1
e
input terminated!
[-1, -1]
the encoded list is [-1, -1, -1, -1]
This is a program to encode or decode bytes based on RLE ALgorithm
(o_O) Choices are:
1: Press 1 to enter the encode mode
2: Press 2 to enter the decode mode
3: Press 3 to Exit!
no such
SOLUTION TO DISCUSS BY #Villat
First of all big thanks to you man for helping and investing time and effort.
Now, i have small question regarding these lines:
if(sc.hasNextInt()) choice=sc.nextInt();
else {
sc.next();
continue;
}
error = false;
So let me see if i got this right, those lines play a role as a precaution,and please correct me if im wrong!, to prevent the Exception from popping up right.
So wouldnt it be enough to write the following ditching the try-catch blocks because NoSuchElementException has no chance to emerge and the InputMismatchException is being treated and prevented by the else block:
while (error){
if(sc.hasNextInt()) choice=sc.nextInt();
else {
sc.next();
continue;
}
error = false;
}
Just for training purpouses if i would like to Handle this error by try-catch block would you consider it clean and immune to Exceptions if i wrote it like this: (ditching the NumberFormatException)
-so Demonstrating the Handle variant of your answer would it be like this right?
while (error){
try {
choice=sc.nextInt();
error = false;
} catch (InputMismatchException /*| NumberFormatException*/ e) {
error = false;
//System.out.println("invalid type or format!");
sc.next();
continue;
}
}

I made a few changes to your code (and removed comments to make it more readable). Basically, I'm only using one Scanner right now, and I'm not moving forward into the options until a sc.nextInt() appears.
public static void main(String[] args){
Scanner sc=new Scanner (System.in);
int choice = 0;
do {
System.out.println("This is a program to encode or decode bytes based on RLE ALgorithm" +
"\n (o_O) Choices are: " +
"\n 1: Press 1 to enter the encode mode" +
"\n 2: Press 2 to enter the decode mode" +
"\n 3: Press 3 to Exit!");
boolean error = true;
while (error){
try {
if(sc.hasNextInt()) choice=sc.nextInt();
else {
sc.next();
continue;
}
error = false;
} catch (InputMismatchException | NumberFormatException e) {
System.out.println("invalid type or format!");
} catch (NoSuchElementException e) {
System.out.println("no such");
}
}
switch(choice){
case 1 :
System.out.println("entering the encode mode!");
System.out.println(input(sc));
break;
case 2 :
//countAndDecode(input(sc));
break;
case 3 :
System.out.println("exiting...");
break;
default :
System.out.println("please enter a valid option and valid format!");
}
} while (choice!=3);
sc.close();
}
Input method:
public static byte [] input(Scanner sc) {
ByteArrayOutputStream inArray= new ByteArrayOutputStream();
System.out.println("enter a sequence of bytes please! ");
System.out.println("non-int will terminate the input!");
while (sc.hasNext()) {
byte i;
try {
i = sc.nextByte();
inArray.write(i);
} catch (InputMismatchException e) {
System.out.println("input terminated!");
break;
}
}
System.out.println(Arrays.toString(inArray.toByteArray()));
return inArray.toByteArray();
}

Related

Scanner does not read user input once the thread throws an exception in Java [duplicate]

This question already has answers here:
How to use Scanner to accept only valid int as input
(6 answers)
Closed 2 years ago.
I have a separate thread class and below is the run method,
#Override
public void run() {
Scanner scanner = new Scanner(System.in);
int iRequestType = 0;
int iRequestId = 0;
while (!exit){
try {
System.out.print("\nRealTime - 1\nHttpUrl - 2\nSelect one : ");
iRequestType = scanner.nextInt(); //it will wait here after the exception occurs
System.out.print("\nEnter Request ID : ");
iRequestId = scanner.nextInt();
if(iRequestType == 1 && !map_RealTimeRequests.isEmpty()){
sendRealTimeRequest(iRequestId);
} else if (iRequestType == 2 && !map_HttpUrlRequests.isEmpty()){
sendHttpUrlRequest(iRequestId);
} else if(iRequestType > 2) {
System.out.println("Invalid List Number");
}else {
System.out.println("Empty List");
}
} catch (InputMismatchException e){
System.out.println("Invalid request type or ID : " + e);
scanner.close();
scanner = new Scanner(System.in);
}
}
}
If I enter numbers, the program works fine. When I enter a character, it goes to the catch block and and execute the lines within it as expected. Once the execution of catch block completes, it will iterate again and ask for the keyboard inputs. But when I try to enter a value (a number or a character), it does not read anything and keep waiting without executing the next lines.
What I want to do is, ask the user to enter a number and if the user enter a character, print an error message in console and iterate the while loop again. How can I solve this issue? Thanks in advance!
You should not call scanner.close() because that closes System.in. You don't want to close System.in you just want to clear out the buffer. You can do that by replacing the scanner as you did (without the close() call), or you can call nextLine() if it's single-line input like this:
} catch (InputMismatchException e){
System.out.println("Invalid request type or ID : " + e);
scanner.nextLine();
}

Why will my exception not print out its print statement? (Java)

The print statement in my exception never prints out. If I do not enter anything it will just continue to ask me to enter name of cruise ship. I need it to throw the exception print statement along with that if someone were to enter an empty string or anything other than a string.
do {
try {
System.out.println("Enter name of cruise ship: ");
cruiseShipName = scnr.nextLine();
}
catch(Exception e){
e.printStackTrace();
System.out.println("Invalid Input. Please try again.");
}
} while (cruiseShipName.equals(""));
Maybe your code will not throw any exception if the scnr.nextLine() is empty.
In your case if you want to ask the user to try again, you could do as following:
`
do {
System.out.println("Enter name of cruise ship: ");
cruiseShipName = scnr.nextLine();
if (cruiseShipName.equals("")) {
System.out.println("Invalid Input. Please try again.");
}
} while (cruiseShipName.equals(""));
`
The may help you.
do {
try {
System.out.println("Enter name of cruise ship: ");
cruiseShipName = scnr.nextLine();
if(cruiseShipName.equals("")) throw new Exception("");
}
catch(Exception e){
e.printStackTrace();
System.out.println("Invalid Input. Please try again.");
}
} while (cruiseShipName.equals(""));
This code doesn't actually throw an exception. You don't have anything that checks if the input is valid and throws an exception if it isn't.
So right now, the input is always valid.

Java InputMismatchException loops with Scanner

first off this is one of my assignments for a class. I understand all the concepts my professor was trying to explain with this assignment but I am having a silly issue with it continuously looping, and cannot figure out how to stop it.
We were required to create our own Exception classes and use throw them at specific instances when a Time (with an hour, minute, and second) object is created. However, I'm not having a problem with my own exception classes, I am having an issue with the InputMismatchException continuously being executed.
This class reads a file through a Scanner object which has a few lines consisting of three integers on each line to represent a time in military format (ex. 20 15 33) is 8:15:33 P.M. but once there is an invalid token (ex. twenty 15 33 , where twenty is not an integer) it just won't stop the InputMismatchException catch block.
This is the code:
public class TimeTestNew
{
public static void main (String[] args)throws IllegalHourException,
IllegalMinuteException,
IllegalSecondException,
FileNotFoundException,
NumberFormatException
{
boolean fileFound = false;
while(!fileFound)
{
String input = JOptionPane.showInputDialog("Enter filename: " );
try
{
Scanner in = new Scanner(new File(input));
fileFound = true;
while(in.hasNextLine())
{
int hour = 0, minute = 0, second = 0;
try
{
hour = in.nextInt();
minute = in.nextInt();
second = in.nextInt();
Time theTime = new Time(hour,minute,second);
System.out.println(theTime);
}
catch(IllegalHourException e)
{
System.err.println("Sorry, \"" + e.value
+ "\" is an invalid hour.");
}
catch(IllegalMinuteException e)
{
System.err.println("Sorry, \"" + e.value
+ "\" is an invalid minute.");
}
catch(IllegalSecondException e)
{
System.err.println("Sorry, \"" + e.value
+ "\" is an invalid second.");
}
catch(NumberFormatException | InputMismatchException e)
{
System.err.println("Incorrect format used.");
// this is what keeps getting executed
}
}
in.close();
}
catch (FileNotFoundException e)
{
System.err.println("ERROR: \"" + input + "\" not found\n"
+ "Please enter a valid filename.");
}
}
}
}
And this is sample output:
12:12:12 P.M.
Sorry, "24" is an invalid hour.
1:02:03 A.M.
1:13:13 P.M.
Sorry, "90" is an invalid minute.
Incorrect format used.
Incorrect format used.
Incorrect format used.
Incorrect format used.
Incorrect format used.
Incorrect format used.
Incorrect format used.
Incorrect format used.
Incorrect format used.
Incorrect format used.
Incorrect format used.
//...and this goes on forever
As you can see, it will loop that "Incorrect format used" inside the catch block for InputMismatchException over and over and over...I cannot figure out a way to get it to stop and continue reading the file.
Any help would be appreciated in explaining a solution, thanks!
The issue is that the while loop's condition isn't on whether the input is valid, but instead if there exists a next line in the file. You should check out the break statement if you don't have the ability to validate input before the while loop.

hasNextInt() From Scanner behaving weirdly

I have a very simple loop that waits for a number (int) and as long as that number is not exitOption it does not leave the loop, however I get an unexpected error, and I don't know what's causing it.
Edit
Adding another snippet so you can compile
public static void main(String[] args) throws FileNotFoundException,
SecurityException,
IOException,
ClassNotFoundException {
while (controller.selectOptionMM());
/Edit
public boolean selectOptionMM() throws SecurityException,
FileNotFoundException,
IOException {
int cmd = ui.getExitOption();
ui.mainMenu();
cmd = utils.readInteger(">>> "); // this is my problem, right here
// code in next snippet
while (cmd <1 || cmd > ui.getExitOption()) {
System.out.println("Invalid command!");
cmd = utils.readInteger(">>> ");
}
switch (cmd) {
case 1:
case 2:
case 3:
case 4: this.repository.close();
return true;
case 5: return false;
}
return false;
}
Here is what fails:
public int readInteger(String cmdPrompt) {
int cmd = 0;
Scanner input = new Scanner(System.in);
System.out.printf(cmdPrompt);
try {
if (input.hasNextInt())
cmd = input.nextInt(); // first time it works
// Second time it does not allow me to input anything
// catches InputMissmatchException, does not print message
// for said catch
// infinitely prints "Invalid command" from previous snippet
} catch (InputMismatchException ime) {
System.out.println("InputMismatchException: " + ime);
} catch (NoSuchElementException nsee) {
System.out.println("NoSuchElementException: " + nsee);
} catch (IllegalStateException ise) {
} finally {
input.close(); // not sure if I should test with if (input != null) THEN close
}
return cmd;
}
First time I pass trough, it reads the number no problem. Now if the number is not 5 (in this case exitOption), it passes again trough readInteger(String cmdPrompt) except this time it jumps to catch (InputMismatchException ime) (debug) except it does not print that message and just jumps to Error, input must be number and Invalid command.
Is something stuck in my input buffer, can I flush it, why is it (input buffer) stuck (with random data)???
I'll try debugging again and see what's stuck in my input buffer, if I can figure out how to see that.
The problem is in the call to input.close() - this causes the underlying input stream to be closed. When the input stream being closed is System.in, bad things happen (namely, you can't read from stdin any more). You should be OK just eliminating this line.
input.hasNextInt()
This line throws the exception if there is no Integer, so instead of it going to else block it forward to catch block. It will never go to else block if exception get caught.

Java accepting only numbers from user with Scanner

I am trying to understand how to only accept numbers from the user, and I have attempted to do so using try catch blocks, but I would still get errors with it.
Scanner scan = new Scanner(System.in);
boolean bidding;
int startbid;
int bid;
bidding = true;
System.out.println("Alright folks, who wants this unit?" +
"\nHow much. How much. How much money where?" );
startbid = scan.nextInt();
try{
while(bidding){
System.out.println("$" + startbid + "! Whose going to bid higher?");
startbid =+ scan.nextInt();
}
}catch(NumberFormatException nfe){
System.out.println("Please enter a bid");
}
I am trying to understand why it is not working.
I tested it out by inputting a into the console, and I would receive an error instead of the hopeful "Please enter a bid" resolution.
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:909)
at java.util.Scanner.next(Scanner.java:1530)
at java.util.Scanner.nextInt(Scanner.java:2160)
at java.util.Scanner.nextInt(Scanner.java:2119)
at Auction.test.main(test.java:25)
Try catching the type of exception thrown rather than NumberFormatException (InputMismatchException).
The message is pretty clear: Scanner.nextInt() throws an InputMismatchException, but your code catches NumberFormatException. Catch the appropriate exception type.
While using Scanner.nextInt(), it causes some problems. When you use Scanner.nextInt(), it does not consume the new line (or other delimiter) itself so the next token returned will typically be an empty string. Thus, you need to follow it with a Scanner.nextLine(). You can discard the result.
It's for this reason that I suggest always using nextLine (or BufferedReader.readLine()) and doing the parsing after using Integer.parseInt(). Your code should be as follows.
Scanner scan = new Scanner(System.in);
boolean bidding;
int startbid;
int bid;
bidding = true;
System.out.print("Alright folks, who wants this unit?" +
"\nHow much. How much. How much money where?" );
try
{
startbid = Integer.parseInt(scan.nextLine());
while(bidding)
{
System.out.println("$" + startbid + "! Whose going to bid higher?");
startbid =+ Integer.parseInt(scan.nextLine());
}
}
catch(NumberFormatException nfe)
{
System.out.println("Please enter a bid");
}

Categories