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:
sc.close()
in main caused the exact same error as above..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 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();
}